aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2009-07-09 20:02:50 -0400
committerSteve French <sfrench@us.ibm.com>2009-07-09 17:15:10 -0400
commit3bbeeb3c93a961bd01b969dd4395ecac0c09db8d (patch)
tree57f003be4cb7a78094a3806df463844371329a85 /fs/cifs
parent654cf14ac0a71c56c1f0032140c3403382ca076b (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>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c63
-rw-r--r--fs/cifs/inode.c11
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
223extern 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
223extern int CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *pTcon, 227extern 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
5118int 5118int
5119CIFSSMBUnixSetFileInfo(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
5181int
5119CIFSSMBUnixSetPathInfo(const int xid, struct cifsTconInfo *tcon, char *fileName, 5182CIFSSMBUnixSetPathInfo(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);