diff options
author | Jeff Layton <jlayton@redhat.com> | 2009-07-09 20:02:50 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2009-07-09 17:15:10 -0400 |
commit | 3bbeeb3c93a961bd01b969dd4395ecac0c09db8d (patch) | |
tree | 57f003be4cb7a78094a3806df463844371329a85 | |
parent | 654cf14ac0a71c56c1f0032140c3403382ca076b (diff) |
cifs: add and use CIFSSMBUnixSetFileInfo for setattr calls
cifs: add and use CIFSSMBUnixSetFileInfo for setattr calls
When there's an open filehandle, SET_FILE_INFO is apparently preferred
over SET_PATH_INFO. Add a new variant that sets a FILE_UNIX_INFO_BASIC
infolevel via SET_FILE_INFO and switch cifs_setattr_unix to use the
new call when there's an open filehandle available.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
-rw-r--r-- | fs/cifs/cifsproto.h | 4 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 63 | ||||
-rw-r--r-- | fs/cifs/inode.c | 11 |
3 files changed, 77 insertions, 1 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index d95fd427de57..37c11c08c529 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -220,6 +220,10 @@ struct cifs_unix_set_info_args { | |||
220 | dev_t device; | 220 | dev_t device; |
221 | }; | 221 | }; |
222 | 222 | ||
223 | extern int CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, | ||
224 | const struct cifs_unix_set_info_args *args, | ||
225 | u16 fid, u32 pid_of_opener); | ||
226 | |||
223 | extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon, | 227 | extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon, |
224 | char *fileName, | 228 | char *fileName, |
225 | const struct cifs_unix_set_info_args *args, | 229 | const struct cifs_unix_set_info_args *args, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 1f3c8a463fcd..922f5fe2084c 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -5116,6 +5116,69 @@ cifs_fill_unix_set_info(FILE_UNIX_BASIC_INFO *data_offset, | |||
5116 | } | 5116 | } |
5117 | 5117 | ||
5118 | int | 5118 | int |
5119 | CIFSSMBUnixSetFileInfo(const int xid, struct cifsTconInfo *tcon, | ||
5120 | const struct cifs_unix_set_info_args *args, | ||
5121 | u16 fid, u32 pid_of_opener) | ||
5122 | { | ||
5123 | struct smb_com_transaction2_sfi_req *pSMB = NULL; | ||
5124 | FILE_UNIX_BASIC_INFO *data_offset; | ||
5125 | int rc = 0; | ||
5126 | u16 params, param_offset, offset, byte_count, count; | ||
5127 | |||
5128 | cFYI(1, ("Set Unix Info (via SetFileInfo)")); | ||
5129 | rc = small_smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB); | ||
5130 | |||
5131 | if (rc) | ||
5132 | return rc; | ||
5133 | |||
5134 | pSMB->hdr.Pid = cpu_to_le16((__u16)pid_of_opener); | ||
5135 | pSMB->hdr.PidHigh = cpu_to_le16((__u16)(pid_of_opener >> 16)); | ||
5136 | |||
5137 | params = 6; | ||
5138 | pSMB->MaxSetupCount = 0; | ||
5139 | pSMB->Reserved = 0; | ||
5140 | pSMB->Flags = 0; | ||
5141 | pSMB->Timeout = 0; | ||
5142 | pSMB->Reserved2 = 0; | ||
5143 | param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; | ||
5144 | offset = param_offset + params; | ||
5145 | |||
5146 | data_offset = (FILE_UNIX_BASIC_INFO *) | ||
5147 | ((char *)(&pSMB->hdr.Protocol) + offset); | ||
5148 | count = sizeof(FILE_UNIX_BASIC_INFO); | ||
5149 | |||
5150 | pSMB->MaxParameterCount = cpu_to_le16(2); | ||
5151 | /* BB find max SMB PDU from sess */ | ||
5152 | pSMB->MaxDataCount = cpu_to_le16(1000); | ||
5153 | pSMB->SetupCount = 1; | ||
5154 | pSMB->Reserved3 = 0; | ||
5155 | pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FILE_INFORMATION); | ||
5156 | byte_count = 3 /* pad */ + params + count; | ||
5157 | pSMB->DataCount = cpu_to_le16(count); | ||
5158 | pSMB->ParameterCount = cpu_to_le16(params); | ||
5159 | pSMB->TotalDataCount = pSMB->DataCount; | ||
5160 | pSMB->TotalParameterCount = pSMB->ParameterCount; | ||
5161 | pSMB->ParameterOffset = cpu_to_le16(param_offset); | ||
5162 | pSMB->DataOffset = cpu_to_le16(offset); | ||
5163 | pSMB->Fid = fid; | ||
5164 | pSMB->InformationLevel = cpu_to_le16(SMB_SET_FILE_UNIX_BASIC); | ||
5165 | pSMB->Reserved4 = 0; | ||
5166 | pSMB->hdr.smb_buf_length += byte_count; | ||
5167 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
5168 | |||
5169 | cifs_fill_unix_set_info(data_offset, args); | ||
5170 | |||
5171 | rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); | ||
5172 | if (rc) | ||
5173 | cFYI(1, ("Send error in Set Time (SetFileInfo) = %d", rc)); | ||
5174 | |||
5175 | /* Note: On -EAGAIN error only caller can retry on handle based calls | ||
5176 | since file handle passed in no longer valid */ | ||
5177 | |||
5178 | return rc; | ||
5179 | } | ||
5180 | |||
5181 | int | ||
5119 | CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, | 5182 | CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, |
5120 | const struct cifs_unix_set_info_args *args, | 5183 | const struct cifs_unix_set_info_args *args, |
5121 | const struct nls_table *nls_codepage, int remap) | 5184 | const struct nls_table *nls_codepage, int remap) |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ad19007ea05f..55b616bb381e 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -1790,6 +1790,7 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1790 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | 1790 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1791 | struct cifsTconInfo *pTcon = cifs_sb->tcon; | 1791 | struct cifsTconInfo *pTcon = cifs_sb->tcon; |
1792 | struct cifs_unix_set_info_args *args = NULL; | 1792 | struct cifs_unix_set_info_args *args = NULL; |
1793 | struct cifsFileInfo *open_file; | ||
1793 | 1794 | ||
1794 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", | 1795 | cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x", |
1795 | direntry->d_name.name, attrs->ia_valid)); | 1796 | direntry->d_name.name, attrs->ia_valid)); |
@@ -1876,10 +1877,18 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs) | |||
1876 | args->ctime = NO_CHANGE_64; | 1877 | args->ctime = NO_CHANGE_64; |
1877 | 1878 | ||
1878 | args->device = 0; | 1879 | args->device = 0; |
1879 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, | 1880 | open_file = find_writable_file(cifsInode); |
1881 | if (open_file) { | ||
1882 | u16 nfid = open_file->netfid; | ||
1883 | u32 npid = open_file->pid; | ||
1884 | rc = CIFSSMBUnixSetFileInfo(xid, pTcon, args, nfid, npid); | ||
1885 | atomic_dec(&open_file->wrtPending); | ||
1886 | } else { | ||
1887 | rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, args, | ||
1880 | cifs_sb->local_nls, | 1888 | cifs_sb->local_nls, |
1881 | cifs_sb->mnt_cifs_flags & | 1889 | cifs_sb->mnt_cifs_flags & |
1882 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1890 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
1891 | } | ||
1883 | 1892 | ||
1884 | if (!rc) | 1893 | if (!rc) |
1885 | rc = inode_setattr(inode, attrs); | 1894 | rc = inode_setattr(inode, attrs); |