aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-02-01 13:52:45 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-02-01 13:52:45 -0500
commit0f44bc36ba1cddbd34371110c4ef8f0800c8d465 (patch)
treece5f664e91af8bc0988830acdacbba5080d9c5f3
parentefc518eb318c4d776933c23e7b82c2e5402b62de (diff)
parenta9a315d41407cd1079eb815f4adae897cc08b0d2 (diff)
Merge branch 'for-linus' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs fixes from Steve French: "A set of cifs fixes (mostly for symlinks, and SMB2 xattrs) and cleanups" * 'for-linus' of git://git.samba.org/sfrench/cifs-2.6: cifs: Fix check for regular file in couldbe_mf_symlink() [CIFS] Fix SMB2 mounts so they don't try to set or get xattrs via cifs CIFS: Cleanup cifs open codepath CIFS: Remove extra indentation in cifs_sfu_type CIFS: Cleanup cifs_mknod CIFS: Cleanup CIFSSMBOpen cifs: Add support for follow_link on dfs shares under posix extensions cifs: move unix extension call to cifs_query_symlink() cifs: Re-order M-F Symlink code cifs: Add create MFSymlinks to protocol ops struct cifs: use protocol specific call for query_mf_symlink() cifs: Rename MF symlink function names cifs: Rename and cleanup open_query_close_cifs_symlink() cifs: Fix memory leak in cifs_hardlink()
-rw-r--r--fs/cifs/cifsacl.c40
-rw-r--r--fs/cifs/cifsglob.h14
-rw-r--r--fs/cifs/cifsproto.h22
-rw-r--r--fs/cifs/cifssmb.c158
-rw-r--r--fs/cifs/dir.c59
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/inode.c178
-rw-r--r--fs/cifs/link.c323
-rw-r--r--fs/cifs/readdir.c2
-rw-r--r--fs/cifs/smb1ops.c126
-rw-r--r--fs/cifs/xattr.c49
11 files changed, 553 insertions, 420 deletions
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 51f5e0ee7237..8f9b4f710d4a 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -895,9 +895,10 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
895 int oplock = 0; 895 int oplock = 0;
896 unsigned int xid; 896 unsigned int xid;
897 int rc, create_options = 0; 897 int rc, create_options = 0;
898 __u16 fid;
899 struct cifs_tcon *tcon; 898 struct cifs_tcon *tcon;
900 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); 899 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
900 struct cifs_fid fid;
901 struct cifs_open_parms oparms;
901 902
902 if (IS_ERR(tlink)) 903 if (IS_ERR(tlink))
903 return ERR_CAST(tlink); 904 return ERR_CAST(tlink);
@@ -908,12 +909,19 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
908 if (backup_cred(cifs_sb)) 909 if (backup_cred(cifs_sb))
909 create_options |= CREATE_OPEN_BACKUP_INTENT; 910 create_options |= CREATE_OPEN_BACKUP_INTENT;
910 911
911 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 912 oparms.tcon = tcon;
912 create_options, &fid, &oplock, NULL, cifs_sb->local_nls, 913 oparms.cifs_sb = cifs_sb;
913 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 914 oparms.desired_access = READ_CONTROL;
915 oparms.create_options = create_options;
916 oparms.disposition = FILE_OPEN;
917 oparms.path = path;
918 oparms.fid = &fid;
919 oparms.reconnect = false;
920
921 rc = CIFS_open(xid, &oparms, &oplock, NULL);
914 if (!rc) { 922 if (!rc) {
915 rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); 923 rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
916 CIFSSMBClose(xid, tcon, fid); 924 CIFSSMBClose(xid, tcon, fid.netfid);
917 } 925 }
918 926
919 cifs_put_tlink(tlink); 927 cifs_put_tlink(tlink);
@@ -950,10 +958,11 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
950 int oplock = 0; 958 int oplock = 0;
951 unsigned int xid; 959 unsigned int xid;
952 int rc, access_flags, create_options = 0; 960 int rc, access_flags, create_options = 0;
953 __u16 fid;
954 struct cifs_tcon *tcon; 961 struct cifs_tcon *tcon;
955 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 962 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
956 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); 963 struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
964 struct cifs_fid fid;
965 struct cifs_open_parms oparms;
957 966
958 if (IS_ERR(tlink)) 967 if (IS_ERR(tlink))
959 return PTR_ERR(tlink); 968 return PTR_ERR(tlink);
@@ -969,18 +978,25 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
969 else 978 else
970 access_flags = WRITE_DAC; 979 access_flags = WRITE_DAC;
971 980
972 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags, 981 oparms.tcon = tcon;
973 create_options, &fid, &oplock, NULL, cifs_sb->local_nls, 982 oparms.cifs_sb = cifs_sb;
974 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 983 oparms.desired_access = access_flags;
984 oparms.create_options = create_options;
985 oparms.disposition = FILE_OPEN;
986 oparms.path = path;
987 oparms.fid = &fid;
988 oparms.reconnect = false;
989
990 rc = CIFS_open(xid, &oparms, &oplock, NULL);
975 if (rc) { 991 if (rc) {
976 cifs_dbg(VFS, "Unable to open file to set ACL\n"); 992 cifs_dbg(VFS, "Unable to open file to set ACL\n");
977 goto out; 993 goto out;
978 } 994 }
979 995
980 rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag); 996 rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
981 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc); 997 cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
982 998
983 CIFSSMBClose(xid, tcon, fid); 999 CIFSSMBClose(xid, tcon, fid.netfid);
984out: 1000out:
985 free_xid(xid); 1001 free_xid(xid);
986 cifs_put_tlink(tlink); 1002 cifs_put_tlink(tlink);
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index f918a998a087..a245d1809ed8 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -370,8 +370,12 @@ struct smb_version_operations {
370 void (*new_lease_key)(struct cifs_fid *); 370 void (*new_lease_key)(struct cifs_fid *);
371 int (*generate_signingkey)(struct cifs_ses *); 371 int (*generate_signingkey)(struct cifs_ses *);
372 int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *); 372 int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *);
373 int (*query_mf_symlink)(const unsigned char *, char *, unsigned int *, 373 int (*query_mf_symlink)(unsigned int, struct cifs_tcon *,
374 struct cifs_sb_info *, unsigned int); 374 struct cifs_sb_info *, const unsigned char *,
375 char *, unsigned int *);
376 int (*create_mf_symlink)(unsigned int, struct cifs_tcon *,
377 struct cifs_sb_info *, const unsigned char *,
378 char *, unsigned int *);
375 /* if we can do cache read operations */ 379 /* if we can do cache read operations */
376 bool (*is_read_op)(__u32); 380 bool (*is_read_op)(__u32);
377 /* set oplock level for the inode */ 381 /* set oplock level for the inode */
@@ -385,6 +389,12 @@ struct smb_version_operations {
385 struct cifsFileInfo *target_file, u64 src_off, u64 len, 389 struct cifsFileInfo *target_file, u64 src_off, u64 len,
386 u64 dest_off); 390 u64 dest_off);
387 int (*validate_negotiate)(const unsigned int, struct cifs_tcon *); 391 int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
392 ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *,
393 const unsigned char *, const unsigned char *, char *,
394 size_t, const struct nls_table *, int);
395 int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
396 const char *, const void *, const __u16,
397 const struct nls_table *, int);
388}; 398};
389 399
390struct smb_version_values { 400struct smb_version_values {
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 2c29db6a247e..79e6e9a93a8c 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -362,11 +362,8 @@ extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
362 const struct nls_table *nls_codepage); 362 const struct nls_table *nls_codepage);
363extern int CIFSSMB_set_compression(const unsigned int xid, 363extern int CIFSSMB_set_compression(const unsigned int xid,
364 struct cifs_tcon *tcon, __u16 fid); 364 struct cifs_tcon *tcon, __u16 fid);
365extern int CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, 365extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
366 const char *fileName, const int disposition, 366 int *oplock, FILE_ALL_INFO *buf);
367 const int access_flags, const int omode,
368 __u16 *netfid, int *pOplock, FILE_ALL_INFO *,
369 const struct nls_table *nls_codepage, int remap);
370extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon, 367extern int SMBLegacyOpen(const unsigned int xid, struct cifs_tcon *tcon,
371 const char *fileName, const int disposition, 368 const char *fileName, const int disposition,
372 const int access_flags, const int omode, 369 const int access_flags, const int omode,
@@ -476,8 +473,8 @@ extern int CIFSSMBSetPosixACL(const unsigned int xid, struct cifs_tcon *tcon,
476extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon, 473extern int CIFSGetExtAttr(const unsigned int xid, struct cifs_tcon *tcon,
477 const int netfid, __u64 *pExtAttrBits, __u64 *pMask); 474 const int netfid, __u64 *pExtAttrBits, __u64 *pMask);
478extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb); 475extern void cifs_autodisable_serverino(struct cifs_sb_info *cifs_sb);
479extern bool CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr); 476extern bool couldbe_mf_symlink(const struct cifs_fattr *fattr);
480extern int CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, 477extern int check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
481 struct cifs_sb_info *cifs_sb, 478 struct cifs_sb_info *cifs_sb,
482 struct cifs_fattr *fattr, 479 struct cifs_fattr *fattr,
483 const unsigned char *path); 480 const unsigned char *path);
@@ -496,7 +493,12 @@ void cifs_writev_complete(struct work_struct *work);
496struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, 493struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages,
497 work_func_t complete); 494 work_func_t complete);
498void cifs_writedata_release(struct kref *refcount); 495void cifs_writedata_release(struct kref *refcount);
499int open_query_close_cifs_symlink(const unsigned char *path, char *pbuf, 496int cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
500 unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb, 497 struct cifs_sb_info *cifs_sb,
501 unsigned int xid); 498 const unsigned char *path, char *pbuf,
499 unsigned int *pbytes_read);
500int cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
501 struct cifs_sb_info *cifs_sb,
502 const unsigned char *path, char *pbuf,
503 unsigned int *pbytes_written);
502#endif /* _CIFSPROTO_H */ 504#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index d707edb6b852..4d881c35eeca 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1273,104 +1273,124 @@ OldOpenRetry:
1273} 1273}
1274 1274
1275int 1275int
1276CIFSSMBOpen(const unsigned int xid, struct cifs_tcon *tcon, 1276CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
1277 const char *fileName, const int openDisposition, 1277 FILE_ALL_INFO *buf)
1278 const int access_flags, const int create_options, __u16 *netfid,
1279 int *pOplock, FILE_ALL_INFO *pfile_info,
1280 const struct nls_table *nls_codepage, int remap)
1281{ 1278{
1282 int rc = -EACCES; 1279 int rc = -EACCES;
1283 OPEN_REQ *pSMB = NULL; 1280 OPEN_REQ *req = NULL;
1284 OPEN_RSP *pSMBr = NULL; 1281 OPEN_RSP *rsp = NULL;
1285 int bytes_returned; 1282 int bytes_returned;
1286 int name_len; 1283 int name_len;
1287 __u16 count; 1284 __u16 count;
1285 struct cifs_sb_info *cifs_sb = oparms->cifs_sb;
1286 struct cifs_tcon *tcon = oparms->tcon;
1287 int remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
1288 const struct nls_table *nls = cifs_sb->local_nls;
1289 int create_options = oparms->create_options;
1290 int desired_access = oparms->desired_access;
1291 int disposition = oparms->disposition;
1292 const char *path = oparms->path;
1288 1293
1289openRetry: 1294openRetry:
1290 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **) &pSMB, 1295 rc = smb_init(SMB_COM_NT_CREATE_ANDX, 24, tcon, (void **)&req,
1291 (void **) &pSMBr); 1296 (void **)&rsp);
1292 if (rc) 1297 if (rc)
1293 return rc; 1298 return rc;
1294 1299
1295 pSMB->AndXCommand = 0xFF; /* none */ 1300 /* no commands go after this */
1301 req->AndXCommand = 0xFF;
1296 1302
1297 if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { 1303 if (req->hdr.Flags2 & SMBFLG2_UNICODE) {
1298 count = 1; /* account for one byte pad to word boundary */ 1304 /* account for one byte pad to word boundary */
1299 name_len = 1305 count = 1;
1300 cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), 1306 name_len = cifsConvertToUTF16((__le16 *)(req->fileName + 1),
1301 fileName, PATH_MAX, nls_codepage, remap); 1307 path, PATH_MAX, nls, remap);
1302 name_len++; /* trailing null */ 1308 /* trailing null */
1309 name_len++;
1303 name_len *= 2; 1310 name_len *= 2;
1304 pSMB->NameLength = cpu_to_le16(name_len); 1311 req->NameLength = cpu_to_le16(name_len);
1305 } else { /* BB improve check for buffer overruns BB */ 1312 } else {
1306 count = 0; /* no pad */ 1313 /* BB improve check for buffer overruns BB */
1307 name_len = strnlen(fileName, PATH_MAX); 1314 /* no pad */
1308 name_len++; /* trailing null */ 1315 count = 0;
1309 pSMB->NameLength = cpu_to_le16(name_len); 1316 name_len = strnlen(path, PATH_MAX);
1310 strncpy(pSMB->fileName, fileName, name_len); 1317 /* trailing null */
1318 name_len++;
1319 req->NameLength = cpu_to_le16(name_len);
1320 strncpy(req->fileName, path, name_len);
1311 } 1321 }
1312 if (*pOplock & REQ_OPLOCK) 1322
1313 pSMB->OpenFlags = cpu_to_le32(REQ_OPLOCK); 1323 if (*oplock & REQ_OPLOCK)
1314 else if (*pOplock & REQ_BATCHOPLOCK) 1324 req->OpenFlags = cpu_to_le32(REQ_OPLOCK);
1315 pSMB->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK); 1325 else if (*oplock & REQ_BATCHOPLOCK)
1316 pSMB->DesiredAccess = cpu_to_le32(access_flags); 1326 req->OpenFlags = cpu_to_le32(REQ_BATCHOPLOCK);
1317 pSMB->AllocationSize = 0; 1327
1318 /* set file as system file if special file such 1328 req->DesiredAccess = cpu_to_le32(desired_access);
1319 as fifo and server expecting SFU style and 1329 req->AllocationSize = 0;
1320 no Unix extensions */ 1330
1331 /*
1332 * Set file as system file if special file such as fifo and server
1333 * expecting SFU style and no Unix extensions.
1334 */
1321 if (create_options & CREATE_OPTION_SPECIAL) 1335 if (create_options & CREATE_OPTION_SPECIAL)
1322 pSMB->FileAttributes = cpu_to_le32(ATTR_SYSTEM); 1336 req->FileAttributes = cpu_to_le32(ATTR_SYSTEM);
1323 else 1337 else
1324 pSMB->FileAttributes = cpu_to_le32(ATTR_NORMAL); 1338 req->FileAttributes = cpu_to_le32(ATTR_NORMAL);
1325 1339
1326 /* XP does not handle ATTR_POSIX_SEMANTICS */ 1340 /*
1327 /* but it helps speed up case sensitive checks for other 1341 * XP does not handle ATTR_POSIX_SEMANTICS but it helps speed up case
1328 servers such as Samba */ 1342 * sensitive checks for other servers such as Samba.
1343 */
1329 if (tcon->ses->capabilities & CAP_UNIX) 1344 if (tcon->ses->capabilities & CAP_UNIX)
1330 pSMB->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS); 1345 req->FileAttributes |= cpu_to_le32(ATTR_POSIX_SEMANTICS);
1331 1346
1332 if (create_options & CREATE_OPTION_READONLY) 1347 if (create_options & CREATE_OPTION_READONLY)
1333 pSMB->FileAttributes |= cpu_to_le32(ATTR_READONLY); 1348 req->FileAttributes |= cpu_to_le32(ATTR_READONLY);
1349
1350 req->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1351 req->CreateDisposition = cpu_to_le32(disposition);
1352 req->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1334 1353
1335 pSMB->ShareAccess = cpu_to_le32(FILE_SHARE_ALL);
1336 pSMB->CreateDisposition = cpu_to_le32(openDisposition);
1337 pSMB->CreateOptions = cpu_to_le32(create_options & CREATE_OPTIONS_MASK);
1338 /* BB Expirement with various impersonation levels and verify */ 1354 /* BB Expirement with various impersonation levels and verify */
1339 pSMB->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION); 1355 req->ImpersonationLevel = cpu_to_le32(SECURITY_IMPERSONATION);
1340 pSMB->SecurityFlags = 1356 req->SecurityFlags = SECURITY_CONTEXT_TRACKING|SECURITY_EFFECTIVE_ONLY;
1341 SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY;
1342 1357
1343 count += name_len; 1358 count += name_len;
1344 inc_rfc1001_len(pSMB, count); 1359 inc_rfc1001_len(req, count);
1345 1360
1346 pSMB->ByteCount = cpu_to_le16(count); 1361 req->ByteCount = cpu_to_le16(count);
1347 /* long_op set to 1 to allow for oplock break timeouts */ 1362 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *)req,
1348 rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, 1363 (struct smb_hdr *)rsp, &bytes_returned, 0);
1349 (struct smb_hdr *)pSMBr, &bytes_returned, 0);
1350 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens); 1364 cifs_stats_inc(&tcon->stats.cifs_stats.num_opens);
1351 if (rc) { 1365 if (rc) {
1352 cifs_dbg(FYI, "Error in Open = %d\n", rc); 1366 cifs_dbg(FYI, "Error in Open = %d\n", rc);
1353 } else { 1367 cifs_buf_release(req);
1354 *pOplock = pSMBr->OplockLevel; /* 1 byte no need to le_to_cpu */ 1368 if (rc == -EAGAIN)
1355 *netfid = pSMBr->Fid; /* cifs fid stays in le */ 1369 goto openRetry;
1356 /* Let caller know file was created so we can set the mode. */ 1370 return rc;
1357 /* Do we care about the CreateAction in any other cases? */
1358 if (cpu_to_le32(FILE_CREATE) == pSMBr->CreateAction)
1359 *pOplock |= CIFS_CREATE_ACTION;
1360 if (pfile_info) {
1361 memcpy((char *)pfile_info, (char *)&pSMBr->CreationTime,
1362 36 /* CreationTime to Attributes */);
1363 /* the file_info buf is endian converted by caller */
1364 pfile_info->AllocationSize = pSMBr->AllocationSize;
1365 pfile_info->EndOfFile = pSMBr->EndOfFile;
1366 pfile_info->NumberOfLinks = cpu_to_le32(1);
1367 pfile_info->DeletePending = 0;
1368 }
1369 } 1371 }
1370 1372
1371 cifs_buf_release(pSMB); 1373 /* 1 byte no need to le_to_cpu */
1372 if (rc == -EAGAIN) 1374 *oplock = rsp->OplockLevel;
1373 goto openRetry; 1375 /* cifs fid stays in le */
1376 oparms->fid->netfid = rsp->Fid;
1377
1378 /* Let caller know file was created so we can set the mode. */
1379 /* Do we care about the CreateAction in any other cases? */
1380 if (cpu_to_le32(FILE_CREATE) == rsp->CreateAction)
1381 *oplock |= CIFS_CREATE_ACTION;
1382
1383 if (buf) {
1384 /* copy from CreationTime to Attributes */
1385 memcpy((char *)buf, (char *)&rsp->CreationTime, 36);
1386 /* the file_info buf is endian converted by caller */
1387 buf->AllocationSize = rsp->AllocationSize;
1388 buf->EndOfFile = rsp->EndOfFile;
1389 buf->NumberOfLinks = cpu_to_le32(1);
1390 buf->DeletePending = 0;
1391 }
1392
1393 cifs_buf_release(req);
1374 return rc; 1394 return rc;
1375} 1395}
1376 1396
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index a514e0a65f69..d3a6796caa5a 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -565,12 +565,13 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
565 int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; 565 int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL;
566 struct cifs_sb_info *cifs_sb; 566 struct cifs_sb_info *cifs_sb;
567 struct tcon_link *tlink; 567 struct tcon_link *tlink;
568 struct cifs_tcon *pTcon; 568 struct cifs_tcon *tcon;
569 struct cifs_io_parms io_parms; 569 struct cifs_io_parms io_parms;
570 char *full_path = NULL; 570 char *full_path = NULL;
571 struct inode *newinode = NULL; 571 struct inode *newinode = NULL;
572 int oplock = 0; 572 int oplock = 0;
573 u16 fileHandle; 573 struct cifs_fid fid;
574 struct cifs_open_parms oparms;
574 FILE_ALL_INFO *buf = NULL; 575 FILE_ALL_INFO *buf = NULL;
575 unsigned int bytes_written; 576 unsigned int bytes_written;
576 struct win_dev *pdev; 577 struct win_dev *pdev;
@@ -583,7 +584,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
583 if (IS_ERR(tlink)) 584 if (IS_ERR(tlink))
584 return PTR_ERR(tlink); 585 return PTR_ERR(tlink);
585 586
586 pTcon = tlink_tcon(tlink); 587 tcon = tlink_tcon(tlink);
587 588
588 xid = get_xid(); 589 xid = get_xid();
589 590
@@ -593,7 +594,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
593 goto mknod_out; 594 goto mknod_out;
594 } 595 }
595 596
596 if (pTcon->unix_ext) { 597 if (tcon->unix_ext) {
597 struct cifs_unix_set_info_args args = { 598 struct cifs_unix_set_info_args args = {
598 .mode = mode & ~current_umask(), 599 .mode = mode & ~current_umask(),
599 .ctime = NO_CHANGE_64, 600 .ctime = NO_CHANGE_64,
@@ -608,7 +609,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
608 args.uid = INVALID_UID; /* no change */ 609 args.uid = INVALID_UID; /* no change */
609 args.gid = INVALID_GID; /* no change */ 610 args.gid = INVALID_GID; /* no change */
610 } 611 }
611 rc = CIFSSMBUnixSetPathInfo(xid, pTcon, full_path, &args, 612 rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args,
612 cifs_sb->local_nls, 613 cifs_sb->local_nls,
613 cifs_sb->mnt_cifs_flags & 614 cifs_sb->mnt_cifs_flags &
614 CIFS_MOUNT_MAP_SPECIAL_CHR); 615 CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -640,42 +641,44 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
640 if (backup_cred(cifs_sb)) 641 if (backup_cred(cifs_sb))
641 create_options |= CREATE_OPEN_BACKUP_INTENT; 642 create_options |= CREATE_OPEN_BACKUP_INTENT;
642 643
643 rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, 644 oparms.tcon = tcon;
644 GENERIC_WRITE, create_options, 645 oparms.cifs_sb = cifs_sb;
645 &fileHandle, &oplock, buf, cifs_sb->local_nls, 646 oparms.desired_access = GENERIC_WRITE;
646 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 647 oparms.create_options = create_options;
648 oparms.disposition = FILE_CREATE;
649 oparms.path = full_path;
650 oparms.fid = &fid;
651 oparms.reconnect = false;
652
653 rc = CIFS_open(xid, &oparms, &oplock, buf);
647 if (rc) 654 if (rc)
648 goto mknod_out; 655 goto mknod_out;
649 656
650 /* BB Do not bother to decode buf since no local inode yet to put 657 /*
651 * timestamps in, but we can reuse it safely */ 658 * BB Do not bother to decode buf since no local inode yet to put
659 * timestamps in, but we can reuse it safely.
660 */
652 661
653 pdev = (struct win_dev *)buf; 662 pdev = (struct win_dev *)buf;
654 io_parms.netfid = fileHandle; 663 io_parms.netfid = fid.netfid;
655 io_parms.pid = current->tgid; 664 io_parms.pid = current->tgid;
656 io_parms.tcon = pTcon; 665 io_parms.tcon = tcon;
657 io_parms.offset = 0; 666 io_parms.offset = 0;
658 io_parms.length = sizeof(struct win_dev); 667 io_parms.length = sizeof(struct win_dev);
659 if (S_ISCHR(mode)) { 668 if (S_ISCHR(mode)) {
660 memcpy(pdev->type, "IntxCHR", 8); 669 memcpy(pdev->type, "IntxCHR", 8);
661 pdev->major = 670 pdev->major = cpu_to_le64(MAJOR(device_number));
662 cpu_to_le64(MAJOR(device_number)); 671 pdev->minor = cpu_to_le64(MINOR(device_number));
663 pdev->minor = 672 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev,
664 cpu_to_le64(MINOR(device_number)); 673 NULL, 0);
665 rc = CIFSSMBWrite(xid, &io_parms,
666 &bytes_written, (char *)pdev,
667 NULL, 0);
668 } else if (S_ISBLK(mode)) { 674 } else if (S_ISBLK(mode)) {
669 memcpy(pdev->type, "IntxBLK", 8); 675 memcpy(pdev->type, "IntxBLK", 8);
670 pdev->major = 676 pdev->major = cpu_to_le64(MAJOR(device_number));
671 cpu_to_le64(MAJOR(device_number)); 677 pdev->minor = cpu_to_le64(MINOR(device_number));
672 pdev->minor = 678 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev,
673 cpu_to_le64(MINOR(device_number)); 679 NULL, 0);
674 rc = CIFSSMBWrite(xid, &io_parms,
675 &bytes_written, (char *)pdev,
676 NULL, 0);
677 } /* else if (S_ISFIFO) */ 680 } /* else if (S_ISFIFO) */
678 CIFSSMBClose(xid, pTcon, fileHandle); 681 CIFSSMBClose(xid, tcon, fid.netfid);
679 d_drop(direntry); 682 d_drop(direntry);
680 683
681 /* FIXME: add code here to set EAs */ 684 /* FIXME: add code here to set EAs */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 5a5a87240fe2..853d6d1cc822 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -678,7 +678,7 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
678 678
679 /* 679 /*
680 * Can not refresh inode by passing in file_info buf to be returned by 680 * Can not refresh inode by passing in file_info buf to be returned by
681 * CIFSSMBOpen and then calling get_inode_info with returned buf since 681 * ops->open and then calling get_inode_info with returned buf since
682 * file might have write behind data that needs to be flushed and server 682 * file might have write behind data that needs to be flushed and server
683 * version of file size can be stale. If we knew for sure that inode was 683 * version of file size can be stale. If we knew for sure that inode was
684 * not dirty locally we could do this. 684 * not dirty locally we could do this.
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 49719b8228e5..9cb9679d7357 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -383,10 +383,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
383 383
384 /* check for Minshall+French symlinks */ 384 /* check for Minshall+French symlinks */
385 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { 385 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
386 int tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, 386 int tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
387 full_path); 387 full_path);
388 if (tmprc) 388 if (tmprc)
389 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); 389 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
390 } 390 }
391 391
392 if (*pinode == NULL) { 392 if (*pinode == NULL) {
@@ -404,18 +404,20 @@ int cifs_get_inode_info_unix(struct inode **pinode,
404} 404}
405 405
406static int 406static int
407cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path, 407cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
408 struct cifs_sb_info *cifs_sb, unsigned int xid) 408 struct cifs_sb_info *cifs_sb, unsigned int xid)
409{ 409{
410 int rc; 410 int rc;
411 int oplock = 0; 411 int oplock = 0;
412 __u16 netfid;
413 struct tcon_link *tlink; 412 struct tcon_link *tlink;
414 struct cifs_tcon *tcon; 413 struct cifs_tcon *tcon;
414 struct cifs_fid fid;
415 struct cifs_open_parms oparms;
415 struct cifs_io_parms io_parms; 416 struct cifs_io_parms io_parms;
416 char buf[24]; 417 char buf[24];
417 unsigned int bytes_read; 418 unsigned int bytes_read;
418 char *pbuf; 419 char *pbuf;
420 int buf_type = CIFS_NO_BUFFER;
419 421
420 pbuf = buf; 422 pbuf = buf;
421 423
@@ -436,62 +438,69 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
436 return PTR_ERR(tlink); 438 return PTR_ERR(tlink);
437 tcon = tlink_tcon(tlink); 439 tcon = tlink_tcon(tlink);
438 440
439 rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, GENERIC_READ, 441 oparms.tcon = tcon;
440 CREATE_NOT_DIR, &netfid, &oplock, NULL, 442 oparms.cifs_sb = cifs_sb;
441 cifs_sb->local_nls, 443 oparms.desired_access = GENERIC_READ;
442 cifs_sb->mnt_cifs_flags & 444 oparms.create_options = CREATE_NOT_DIR;
443 CIFS_MOUNT_MAP_SPECIAL_CHR); 445 oparms.disposition = FILE_OPEN;
444 if (rc == 0) { 446 oparms.path = path;
445 int buf_type = CIFS_NO_BUFFER; 447 oparms.fid = &fid;
446 /* Read header */ 448 oparms.reconnect = false;
447 io_parms.netfid = netfid; 449
448 io_parms.pid = current->tgid; 450 rc = CIFS_open(xid, &oparms, &oplock, NULL);
449 io_parms.tcon = tcon; 451 if (rc) {
450 io_parms.offset = 0; 452 cifs_put_tlink(tlink);
451 io_parms.length = 24; 453 return rc;
452 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, 454 }
453 &buf_type); 455
454 if ((rc == 0) && (bytes_read >= 8)) { 456 /* Read header */
455 if (memcmp("IntxBLK", pbuf, 8) == 0) { 457 io_parms.netfid = fid.netfid;
456 cifs_dbg(FYI, "Block device\n"); 458 io_parms.pid = current->tgid;
457 fattr->cf_mode |= S_IFBLK; 459 io_parms.tcon = tcon;
458 fattr->cf_dtype = DT_BLK; 460 io_parms.offset = 0;
459 if (bytes_read == 24) { 461 io_parms.length = 24;
460 /* we have enough to decode dev num */ 462
461 __u64 mjr; /* major */ 463 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
462 __u64 mnr; /* minor */ 464 if ((rc == 0) && (bytes_read >= 8)) {
463 mjr = le64_to_cpu(*(__le64 *)(pbuf+8)); 465 if (memcmp("IntxBLK", pbuf, 8) == 0) {
464 mnr = le64_to_cpu(*(__le64 *)(pbuf+16)); 466 cifs_dbg(FYI, "Block device\n");
465 fattr->cf_rdev = MKDEV(mjr, mnr); 467 fattr->cf_mode |= S_IFBLK;
466 } 468 fattr->cf_dtype = DT_BLK;
467 } else if (memcmp("IntxCHR", pbuf, 8) == 0) { 469 if (bytes_read == 24) {
468 cifs_dbg(FYI, "Char device\n"); 470 /* we have enough to decode dev num */
469 fattr->cf_mode |= S_IFCHR; 471 __u64 mjr; /* major */
470 fattr->cf_dtype = DT_CHR; 472 __u64 mnr; /* minor */
471 if (bytes_read == 24) { 473 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
472 /* we have enough to decode dev num */ 474 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
473 __u64 mjr; /* major */ 475 fattr->cf_rdev = MKDEV(mjr, mnr);
474 __u64 mnr; /* minor */
475 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
476 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
477 fattr->cf_rdev = MKDEV(mjr, mnr);
478 }
479 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
480 cifs_dbg(FYI, "Symlink\n");
481 fattr->cf_mode |= S_IFLNK;
482 fattr->cf_dtype = DT_LNK;
483 } else {
484 fattr->cf_mode |= S_IFREG; /* file? */
485 fattr->cf_dtype = DT_REG;
486 rc = -EOPNOTSUPP;
487 } 476 }
477 } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
478 cifs_dbg(FYI, "Char device\n");
479 fattr->cf_mode |= S_IFCHR;
480 fattr->cf_dtype = DT_CHR;
481 if (bytes_read == 24) {
482 /* we have enough to decode dev num */
483 __u64 mjr; /* major */
484 __u64 mnr; /* minor */
485 mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
486 mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
487 fattr->cf_rdev = MKDEV(mjr, mnr);
488 }
489 } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
490 cifs_dbg(FYI, "Symlink\n");
491 fattr->cf_mode |= S_IFLNK;
492 fattr->cf_dtype = DT_LNK;
488 } else { 493 } else {
489 fattr->cf_mode |= S_IFREG; /* then it is a file */ 494 fattr->cf_mode |= S_IFREG; /* file? */
490 fattr->cf_dtype = DT_REG; 495 fattr->cf_dtype = DT_REG;
491 rc = -EOPNOTSUPP; /* or some unknown SFU type */ 496 rc = -EOPNOTSUPP;
492 } 497 }
493 CIFSSMBClose(xid, tcon, netfid); 498 } else {
499 fattr->cf_mode |= S_IFREG; /* then it is a file */
500 fattr->cf_dtype = DT_REG;
501 rc = -EOPNOTSUPP; /* or some unknown SFU type */
494 } 502 }
503 CIFSSMBClose(xid, tcon, fid.netfid);
495 cifs_put_tlink(tlink); 504 cifs_put_tlink(tlink);
496 return rc; 505 return rc;
497} 506}
@@ -800,10 +809,10 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
800 809
801 /* check for Minshall+French symlinks */ 810 /* check for Minshall+French symlinks */
802 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) { 811 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) {
803 tmprc = CIFSCheckMFSymlink(xid, tcon, cifs_sb, &fattr, 812 tmprc = check_mf_symlink(xid, tcon, cifs_sb, &fattr,
804 full_path); 813 full_path);
805 if (tmprc) 814 if (tmprc)
806 cifs_dbg(FYI, "CIFSCheckMFSymlink: %d\n", tmprc); 815 cifs_dbg(FYI, "check_mf_symlink: %d\n", tmprc);
807 } 816 }
808 817
809 if (!*inode) { 818 if (!*inode) {
@@ -1032,7 +1041,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1032{ 1041{
1033 int oplock = 0; 1042 int oplock = 0;
1034 int rc; 1043 int rc;
1035 __u16 netfid; 1044 struct cifs_fid fid;
1045 struct cifs_open_parms oparms;
1036 struct inode *inode = dentry->d_inode; 1046 struct inode *inode = dentry->d_inode;
1037 struct cifsInodeInfo *cifsInode = CIFS_I(inode); 1047 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
1038 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1048 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
@@ -1055,10 +1065,16 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1055 goto out; 1065 goto out;
1056 } 1066 }
1057 1067
1058 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, 1068 oparms.tcon = tcon;
1059 DELETE|FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, 1069 oparms.cifs_sb = cifs_sb;
1060 &netfid, &oplock, NULL, cifs_sb->local_nls, 1070 oparms.desired_access = DELETE | FILE_WRITE_ATTRIBUTES;
1061 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 1071 oparms.create_options = CREATE_NOT_DIR;
1072 oparms.disposition = FILE_OPEN;
1073 oparms.path = full_path;
1074 oparms.fid = &fid;
1075 oparms.reconnect = false;
1076
1077 rc = CIFS_open(xid, &oparms, &oplock, NULL);
1062 if (rc != 0) 1078 if (rc != 0)
1063 goto out; 1079 goto out;
1064 1080
@@ -1079,7 +1095,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1079 goto out_close; 1095 goto out_close;
1080 } 1096 }
1081 info_buf->Attributes = cpu_to_le32(dosattr); 1097 info_buf->Attributes = cpu_to_le32(dosattr);
1082 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, 1098 rc = CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
1083 current->tgid); 1099 current->tgid);
1084 /* although we would like to mark the file hidden 1100 /* although we would like to mark the file hidden
1085 if that fails we will still try to rename it */ 1101 if that fails we will still try to rename it */
@@ -1090,7 +1106,8 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1090 } 1106 }
1091 1107
1092 /* rename the file */ 1108 /* rename the file */
1093 rc = CIFSSMBRenameOpenFile(xid, tcon, netfid, NULL, cifs_sb->local_nls, 1109 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, NULL,
1110 cifs_sb->local_nls,
1094 cifs_sb->mnt_cifs_flags & 1111 cifs_sb->mnt_cifs_flags &
1095 CIFS_MOUNT_MAP_SPECIAL_CHR); 1112 CIFS_MOUNT_MAP_SPECIAL_CHR);
1096 if (rc != 0) { 1113 if (rc != 0) {
@@ -1100,7 +1117,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1100 1117
1101 /* try to set DELETE_ON_CLOSE */ 1118 /* try to set DELETE_ON_CLOSE */
1102 if (!cifsInode->delete_pending) { 1119 if (!cifsInode->delete_pending) {
1103 rc = CIFSSMBSetFileDisposition(xid, tcon, true, netfid, 1120 rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
1104 current->tgid); 1121 current->tgid);
1105 /* 1122 /*
1106 * some samba versions return -ENOENT when we try to set the 1123 * some samba versions return -ENOENT when we try to set the
@@ -1120,7 +1137,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
1120 } 1137 }
1121 1138
1122out_close: 1139out_close:
1123 CIFSSMBClose(xid, tcon, netfid); 1140 CIFSSMBClose(xid, tcon, fid.netfid);
1124out: 1141out:
1125 kfree(info_buf); 1142 kfree(info_buf);
1126 cifs_put_tlink(tlink); 1143 cifs_put_tlink(tlink);
@@ -1132,13 +1149,13 @@ out:
1132 * them anyway. 1149 * them anyway.
1133 */ 1150 */
1134undo_rename: 1151undo_rename:
1135 CIFSSMBRenameOpenFile(xid, tcon, netfid, dentry->d_name.name, 1152 CIFSSMBRenameOpenFile(xid, tcon, fid.netfid, dentry->d_name.name,
1136 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 1153 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1137 CIFS_MOUNT_MAP_SPECIAL_CHR); 1154 CIFS_MOUNT_MAP_SPECIAL_CHR);
1138undo_setattr: 1155undo_setattr:
1139 if (dosattr != origattr) { 1156 if (dosattr != origattr) {
1140 info_buf->Attributes = cpu_to_le32(origattr); 1157 info_buf->Attributes = cpu_to_le32(origattr);
1141 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, netfid, 1158 if (!CIFSSMBSetFileInfo(xid, tcon, info_buf, fid.netfid,
1142 current->tgid)) 1159 current->tgid))
1143 cifsInode->cifsAttrs = origattr; 1160 cifsInode->cifsAttrs = origattr;
1144 } 1161 }
@@ -1549,7 +1566,8 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1549 struct tcon_link *tlink; 1566 struct tcon_link *tlink;
1550 struct cifs_tcon *tcon; 1567 struct cifs_tcon *tcon;
1551 struct TCP_Server_Info *server; 1568 struct TCP_Server_Info *server;
1552 __u16 srcfid; 1569 struct cifs_fid fid;
1570 struct cifs_open_parms oparms;
1553 int oplock, rc; 1571 int oplock, rc;
1554 1572
1555 tlink = cifs_sb_tlink(cifs_sb); 1573 tlink = cifs_sb_tlink(cifs_sb);
@@ -1576,17 +1594,23 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
1576 if (to_dentry->d_parent != from_dentry->d_parent) 1594 if (to_dentry->d_parent != from_dentry->d_parent)
1577 goto do_rename_exit; 1595 goto do_rename_exit;
1578 1596
1597 oparms.tcon = tcon;
1598 oparms.cifs_sb = cifs_sb;
1579 /* open the file to be renamed -- we need DELETE perms */ 1599 /* open the file to be renamed -- we need DELETE perms */
1580 rc = CIFSSMBOpen(xid, tcon, from_path, FILE_OPEN, DELETE, 1600 oparms.desired_access = DELETE;
1581 CREATE_NOT_DIR, &srcfid, &oplock, NULL, 1601 oparms.create_options = CREATE_NOT_DIR;
1582 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 1602 oparms.disposition = FILE_OPEN;
1583 CIFS_MOUNT_MAP_SPECIAL_CHR); 1603 oparms.path = from_path;
1604 oparms.fid = &fid;
1605 oparms.reconnect = false;
1606
1607 rc = CIFS_open(xid, &oparms, &oplock, NULL);
1584 if (rc == 0) { 1608 if (rc == 0) {
1585 rc = CIFSSMBRenameOpenFile(xid, tcon, srcfid, 1609 rc = CIFSSMBRenameOpenFile(xid, tcon, fid.netfid,
1586 (const char *) to_dentry->d_name.name, 1610 (const char *) to_dentry->d_name.name,
1587 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 1611 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
1588 CIFS_MOUNT_MAP_SPECIAL_CHR); 1612 CIFS_MOUNT_MAP_SPECIAL_CHR);
1589 CIFSSMBClose(xid, tcon, srcfid); 1613 CIFSSMBClose(xid, tcon, fid.netfid);
1590 } 1614 }
1591do_rename_exit: 1615do_rename_exit:
1592 cifs_put_tlink(tlink); 1616 cifs_put_tlink(tlink);
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 92aee08483a5..264ece71bdb2 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -29,6 +29,10 @@
29#include "cifs_debug.h" 29#include "cifs_debug.h"
30#include "cifs_fs_sb.h" 30#include "cifs_fs_sb.h"
31 31
32/*
33 * M-F Symlink Functions - Begin
34 */
35
32#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1) 36#define CIFS_MF_SYMLINK_LEN_OFFSET (4+1)
33#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1)) 37#define CIFS_MF_SYMLINK_MD5_OFFSET (CIFS_MF_SYMLINK_LEN_OFFSET+(4+1))
34#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1)) 38#define CIFS_MF_SYMLINK_LINK_OFFSET (CIFS_MF_SYMLINK_MD5_OFFSET+(32+1))
@@ -91,10 +95,8 @@ symlink_hash_err:
91} 95}
92 96
93static int 97static int
94CIFSParseMFSymlink(const u8 *buf, 98parse_mf_symlink(const u8 *buf, unsigned int buf_len, unsigned int *_link_len,
95 unsigned int buf_len, 99 char **_link_str)
96 unsigned int *_link_len,
97 char **_link_str)
98{ 100{
99 int rc; 101 int rc;
100 unsigned int link_len; 102 unsigned int link_len;
@@ -137,7 +139,7 @@ CIFSParseMFSymlink(const u8 *buf,
137} 139}
138 140
139static int 141static int
140CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) 142format_mf_symlink(u8 *buf, unsigned int buf_len, const char *link_str)
141{ 143{
142 int rc; 144 int rc;
143 unsigned int link_len; 145 unsigned int link_len;
@@ -180,190 +182,94 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str)
180 return 0; 182 return 0;
181} 183}
182 184
185bool
186couldbe_mf_symlink(const struct cifs_fattr *fattr)
187{
188 if (!S_ISREG(fattr->cf_mode))
189 /* it's not a symlink */
190 return false;
191
192 if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE)
193 /* it's not a symlink */
194 return false;
195
196 return true;
197}
198
183static int 199static int
184CIFSCreateMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, 200create_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
185 const char *fromName, const char *toName, 201 struct cifs_sb_info *cifs_sb, const char *fromName,
186 struct cifs_sb_info *cifs_sb) 202 const char *toName)
187{ 203{
188 int rc; 204 int rc;
189 int oplock = 0;
190 int remap;
191 int create_options = CREATE_NOT_DIR;
192 __u16 netfid = 0;
193 u8 *buf; 205 u8 *buf;
194 unsigned int bytes_written = 0; 206 unsigned int bytes_written = 0;
195 struct cifs_io_parms io_parms;
196 struct nls_table *nls_codepage;
197
198 nls_codepage = cifs_sb->local_nls;
199 remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR;
200 207
201 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); 208 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
202 if (!buf) 209 if (!buf)
203 return -ENOMEM; 210 return -ENOMEM;
204 211
205 rc = CIFSFormatMFSymlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName); 212 rc = format_mf_symlink(buf, CIFS_MF_SYMLINK_FILE_SIZE, toName);
206 if (rc != 0) { 213 if (rc)
207 kfree(buf); 214 goto out;
208 return rc;
209 }
210
211 if (backup_cred(cifs_sb))
212 create_options |= CREATE_OPEN_BACKUP_INTENT;
213
214 rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE,
215 create_options, &netfid, &oplock, NULL,
216 nls_codepage, remap);
217 if (rc != 0) {
218 kfree(buf);
219 return rc;
220 }
221
222 io_parms.netfid = netfid;
223 io_parms.pid = current->tgid;
224 io_parms.tcon = tcon;
225 io_parms.offset = 0;
226 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
227 215
228 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, buf, NULL, 0); 216 rc = tcon->ses->server->ops->create_mf_symlink(xid, tcon, cifs_sb,
229 CIFSSMBClose(xid, tcon, netfid); 217 fromName, buf, &bytes_written);
230 kfree(buf); 218 if (rc)
231 if (rc != 0) 219 goto out;
232 return rc;
233 220
234 if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE) 221 if (bytes_written != CIFS_MF_SYMLINK_FILE_SIZE)
235 return -EIO; 222 rc = -EIO;
236 223out:
237 return 0; 224 kfree(buf);
225 return rc;
238} 226}
239 227
240static int 228static int
241CIFSQueryMFSymLink(const unsigned int xid, struct cifs_tcon *tcon, 229query_mf_symlink(const unsigned int xid, struct cifs_tcon *tcon,
242 const unsigned char *searchName, char **symlinkinfo, 230 struct cifs_sb_info *cifs_sb, const unsigned char *path,
243 const struct nls_table *nls_codepage, int remap) 231 char **symlinkinfo)
244{ 232{
245 int rc; 233 int rc;
246 int oplock = 0; 234 u8 *buf = NULL;
247 __u16 netfid = 0;
248 u8 *buf;
249 char *pbuf;
250 unsigned int bytes_read = 0;
251 int buf_type = CIFS_NO_BUFFER;
252 unsigned int link_len = 0; 235 unsigned int link_len = 0;
253 struct cifs_io_parms io_parms; 236 unsigned int bytes_read = 0;
254 FILE_ALL_INFO file_info;
255
256 rc = CIFSSMBOpen(xid, tcon, searchName, FILE_OPEN, GENERIC_READ,
257 CREATE_NOT_DIR, &netfid, &oplock, &file_info,
258 nls_codepage, remap);
259 if (rc != 0)
260 return rc;
261
262 if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
263 CIFSSMBClose(xid, tcon, netfid);
264 /* it's not a symlink */
265 return -EINVAL;
266 }
267 237
268 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); 238 buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL);
269 if (!buf) 239 if (!buf)
270 return -ENOMEM; 240 return -ENOMEM;
271 pbuf = buf;
272 io_parms.netfid = netfid;
273 io_parms.pid = current->tgid;
274 io_parms.tcon = tcon;
275 io_parms.offset = 0;
276 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
277
278 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type);
279 CIFSSMBClose(xid, tcon, netfid);
280 if (rc != 0) {
281 kfree(buf);
282 return rc;
283 }
284
285 rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, symlinkinfo);
286 kfree(buf);
287 if (rc != 0)
288 return rc;
289
290 return 0;
291}
292
293bool
294CIFSCouldBeMFSymlink(const struct cifs_fattr *fattr)
295{
296 if (!(fattr->cf_mode & S_IFREG))
297 /* it's not a symlink */
298 return false;
299 241
300 if (fattr->cf_eof != CIFS_MF_SYMLINK_FILE_SIZE) 242 if (tcon->ses->server->ops->query_mf_symlink)
301 /* it's not a symlink */ 243 rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
302 return false; 244 cifs_sb, path, buf, &bytes_read);
303 245 else
304 return true; 246 rc = -ENOSYS;
305}
306
307int
308open_query_close_cifs_symlink(const unsigned char *path, char *pbuf,
309 unsigned int *pbytes_read, struct cifs_sb_info *cifs_sb,
310 unsigned int xid)
311{
312 int rc;
313 int oplock = 0;
314 __u16 netfid = 0;
315 struct tcon_link *tlink;
316 struct cifs_tcon *ptcon;
317 struct cifs_io_parms io_parms;
318 int buf_type = CIFS_NO_BUFFER;
319 FILE_ALL_INFO file_info;
320
321 tlink = cifs_sb_tlink(cifs_sb);
322 if (IS_ERR(tlink))
323 return PTR_ERR(tlink);
324 ptcon = tlink_tcon(tlink);
325 247
326 rc = CIFSSMBOpen(xid, ptcon, path, FILE_OPEN, GENERIC_READ, 248 if (rc)
327 CREATE_NOT_DIR, &netfid, &oplock, &file_info, 249 goto out;
328 cifs_sb->local_nls,
329 cifs_sb->mnt_cifs_flags &
330 CIFS_MOUNT_MAP_SPECIAL_CHR);
331 if (rc != 0) {
332 cifs_put_tlink(tlink);
333 return rc;
334 }
335 250
336 if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) { 251 if (bytes_read == 0) { /* not a symlink */
337 CIFSSMBClose(xid, ptcon, netfid); 252 rc = -EINVAL;
338 cifs_put_tlink(tlink); 253 goto out;
339 /* it's not a symlink */
340 return rc;
341 } 254 }
342 255
343 io_parms.netfid = netfid; 256 rc = parse_mf_symlink(buf, bytes_read, &link_len, symlinkinfo);
344 io_parms.pid = current->tgid; 257out:
345 io_parms.tcon = ptcon; 258 kfree(buf);
346 io_parms.offset = 0;
347 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
348
349 rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
350 CIFSSMBClose(xid, ptcon, netfid);
351 cifs_put_tlink(tlink);
352 return rc; 259 return rc;
353} 260}
354 261
355
356int 262int
357CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon, 263check_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
358 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, 264 struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
359 const unsigned char *path) 265 const unsigned char *path)
360{ 266{
361 int rc; 267 int rc;
362 u8 *buf = NULL; 268 u8 *buf = NULL;
363 unsigned int link_len = 0; 269 unsigned int link_len = 0;
364 unsigned int bytes_read = 0; 270 unsigned int bytes_read = 0;
365 271
366 if (!CIFSCouldBeMFSymlink(fattr)) 272 if (!couldbe_mf_symlink(fattr))
367 /* it's not a symlink */ 273 /* it's not a symlink */
368 return 0; 274 return 0;
369 275
@@ -372,8 +278,8 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
372 return -ENOMEM; 278 return -ENOMEM;
373 279
374 if (tcon->ses->server->ops->query_mf_symlink) 280 if (tcon->ses->server->ops->query_mf_symlink)
375 rc = tcon->ses->server->ops->query_mf_symlink(path, buf, 281 rc = tcon->ses->server->ops->query_mf_symlink(xid, tcon,
376 &bytes_read, cifs_sb, xid); 282 cifs_sb, path, buf, &bytes_read);
377 else 283 else
378 rc = -ENOSYS; 284 rc = -ENOSYS;
379 285
@@ -383,7 +289,7 @@ CIFSCheckMFSymlink(unsigned int xid, struct cifs_tcon *tcon,
383 if (bytes_read == 0) /* not a symlink */ 289 if (bytes_read == 0) /* not a symlink */
384 goto out; 290 goto out;
385 291
386 rc = CIFSParseMFSymlink(buf, bytes_read, &link_len, NULL); 292 rc = parse_mf_symlink(buf, bytes_read, &link_len, NULL);
387 if (rc == -EINVAL) { 293 if (rc == -EINVAL) {
388 /* it's not a symlink */ 294 /* it's not a symlink */
389 rc = 0; 295 rc = 0;
@@ -403,6 +309,95 @@ out:
403 return rc; 309 return rc;
404} 310}
405 311
312/*
313 * SMB 1.0 Protocol specific functions
314 */
315
316int
317cifs_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
318 struct cifs_sb_info *cifs_sb, const unsigned char *path,
319 char *pbuf, unsigned int *pbytes_read)
320{
321 int rc;
322 int oplock = 0;
323 struct cifs_fid fid;
324 struct cifs_open_parms oparms;
325 struct cifs_io_parms io_parms;
326 int buf_type = CIFS_NO_BUFFER;
327 FILE_ALL_INFO file_info;
328
329 oparms.tcon = tcon;
330 oparms.cifs_sb = cifs_sb;
331 oparms.desired_access = GENERIC_READ;
332 oparms.create_options = CREATE_NOT_DIR;
333 oparms.disposition = FILE_OPEN;
334 oparms.path = path;
335 oparms.fid = &fid;
336 oparms.reconnect = false;
337
338 rc = CIFS_open(xid, &oparms, &oplock, &file_info);
339 if (rc)
340 return rc;
341
342 if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE))
343 /* it's not a symlink */
344 goto out;
345
346 io_parms.netfid = fid.netfid;
347 io_parms.pid = current->tgid;
348 io_parms.tcon = tcon;
349 io_parms.offset = 0;
350 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
351
352 rc = CIFSSMBRead(xid, &io_parms, pbytes_read, &pbuf, &buf_type);
353out:
354 CIFSSMBClose(xid, tcon, fid.netfid);
355 return rc;
356}
357
358int
359cifs_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
360 struct cifs_sb_info *cifs_sb, const unsigned char *path,
361 char *pbuf, unsigned int *pbytes_written)
362{
363 int rc;
364 int oplock = 0;
365 struct cifs_fid fid;
366 struct cifs_open_parms oparms;
367 struct cifs_io_parms io_parms;
368 int create_options = CREATE_NOT_DIR;
369
370 if (backup_cred(cifs_sb))
371 create_options |= CREATE_OPEN_BACKUP_INTENT;
372
373 oparms.tcon = tcon;
374 oparms.cifs_sb = cifs_sb;
375 oparms.desired_access = GENERIC_WRITE;
376 oparms.create_options = create_options;
377 oparms.disposition = FILE_OPEN;
378 oparms.path = path;
379 oparms.fid = &fid;
380 oparms.reconnect = false;
381
382 rc = CIFS_open(xid, &oparms, &oplock, NULL);
383 if (rc)
384 return rc;
385
386 io_parms.netfid = fid.netfid;
387 io_parms.pid = current->tgid;
388 io_parms.tcon = tcon;
389 io_parms.offset = 0;
390 io_parms.length = CIFS_MF_SYMLINK_FILE_SIZE;
391
392 rc = CIFSSMBWrite(xid, &io_parms, pbytes_written, pbuf, NULL, 0);
393 CIFSSMBClose(xid, tcon, fid.netfid);
394 return rc;
395}
396
397/*
398 * M-F Symlink Functions - End
399 */
400
406int 401int
407cifs_hardlink(struct dentry *old_file, struct inode *inode, 402cifs_hardlink(struct dentry *old_file, struct inode *inode,
408 struct dentry *direntry) 403 struct dentry *direntry)
@@ -438,8 +433,10 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
438 CIFS_MOUNT_MAP_SPECIAL_CHR); 433 CIFS_MOUNT_MAP_SPECIAL_CHR);
439 else { 434 else {
440 server = tcon->ses->server; 435 server = tcon->ses->server;
441 if (!server->ops->create_hardlink) 436 if (!server->ops->create_hardlink) {
442 return -ENOSYS; 437 rc = -ENOSYS;
438 goto cifs_hl_exit;
439 }
443 rc = server->ops->create_hardlink(xid, tcon, from_name, to_name, 440 rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
444 cifs_sb); 441 cifs_sb);
445 if ((rc == -EIO) || (rc == -EINVAL)) 442 if ((rc == -EIO) || (rc == -EINVAL))
@@ -530,15 +527,10 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
530 * and fallback to UNIX Extensions Symlinks. 527 * and fallback to UNIX Extensions Symlinks.
531 */ 528 */
532 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) 529 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
533 rc = CIFSQueryMFSymLink(xid, tcon, full_path, &target_path, 530 rc = query_mf_symlink(xid, tcon, cifs_sb, full_path,
534 cifs_sb->local_nls, 531 &target_path);
535 cifs_sb->mnt_cifs_flags &
536 CIFS_MOUNT_MAP_SPECIAL_CHR);
537 532
538 if ((rc != 0) && cap_unix(tcon->ses)) 533 if (rc != 0 && server->ops->query_symlink)
539 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, &target_path,
540 cifs_sb->local_nls);
541 else if (rc != 0 && server->ops->query_symlink)
542 rc = server->ops->query_symlink(xid, tcon, full_path, 534 rc = server->ops->query_symlink(xid, tcon, full_path,
543 &target_path, cifs_sb); 535 &target_path, cifs_sb);
544 536
@@ -587,8 +579,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
587 579
588 /* BB what if DFS and this volume is on different share? BB */ 580 /* BB what if DFS and this volume is on different share? BB */
589 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) 581 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS)
590 rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, 582 rc = create_mf_symlink(xid, pTcon, cifs_sb, full_path, symname);
591 cifs_sb);
592 else if (pTcon->unix_ext) 583 else if (pTcon->unix_ext)
593 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, 584 rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname,
594 cifs_sb->local_nls); 585 cifs_sb->local_nls);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 5940ecabbe6a..b15862e0f68c 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -749,7 +749,7 @@ static int cifs_filldir(char *find_entry, struct file *file,
749 } 749 }
750 750
751 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) && 751 if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) &&
752 CIFSCouldBeMFSymlink(&fattr)) 752 couldbe_mf_symlink(&fattr))
753 /* 753 /*
754 * trying to get the type and mode can be slow, 754 * trying to get the type and mode can be slow,
755 * so just call those regular files for now, and mark 755 * so just call those regular files for now, and mark
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 5f5ba0dc2ee1..9ac5bfc9cc56 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -560,17 +560,24 @@ cifs_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
560 if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) { 560 if (!rc && (le32_to_cpu(data->Attributes) & ATTR_REPARSE)) {
561 int tmprc; 561 int tmprc;
562 int oplock = 0; 562 int oplock = 0;
563 __u16 netfid; 563 struct cifs_fid fid;
564 struct cifs_open_parms oparms;
565
566 oparms.tcon = tcon;
567 oparms.cifs_sb = cifs_sb;
568 oparms.desired_access = FILE_READ_ATTRIBUTES;
569 oparms.create_options = 0;
570 oparms.disposition = FILE_OPEN;
571 oparms.path = full_path;
572 oparms.fid = &fid;
573 oparms.reconnect = false;
564 574
565 /* Need to check if this is a symbolic link or not */ 575 /* Need to check if this is a symbolic link or not */
566 tmprc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, 576 tmprc = CIFS_open(xid, &oparms, &oplock, NULL);
567 FILE_READ_ATTRIBUTES, 0, &netfid, &oplock,
568 NULL, cifs_sb->local_nls,
569 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
570 if (tmprc == -EOPNOTSUPP) 577 if (tmprc == -EOPNOTSUPP)
571 *symlink = true; 578 *symlink = true;
572 else 579 else
573 CIFSSMBClose(xid, tcon, netfid); 580 CIFSSMBClose(xid, tcon, fid.netfid);
574 } 581 }
575 582
576 return rc; 583 return rc;
@@ -705,12 +712,7 @@ cifs_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
705 oparms->cifs_sb->local_nls, 712 oparms->cifs_sb->local_nls,
706 oparms->cifs_sb->mnt_cifs_flags 713 oparms->cifs_sb->mnt_cifs_flags
707 & CIFS_MOUNT_MAP_SPECIAL_CHR); 714 & CIFS_MOUNT_MAP_SPECIAL_CHR);
708 return CIFSSMBOpen(xid, oparms->tcon, oparms->path, 715 return CIFS_open(xid, oparms, oplock, buf);
709 oparms->disposition, oparms->desired_access,
710 oparms->create_options, &oparms->fid->netfid, oplock,
711 buf, oparms->cifs_sb->local_nls,
712 oparms->cifs_sb->mnt_cifs_flags &
713 CIFS_MOUNT_MAP_SPECIAL_CHR);
714} 716}
715 717
716static void 718static void
@@ -761,8 +763,9 @@ smb_set_file_info(struct inode *inode, const char *full_path,
761{ 763{
762 int oplock = 0; 764 int oplock = 0;
763 int rc; 765 int rc;
764 __u16 netfid;
765 __u32 netpid; 766 __u32 netpid;
767 struct cifs_fid fid;
768 struct cifs_open_parms oparms;
766 struct cifsFileInfo *open_file; 769 struct cifsFileInfo *open_file;
767 struct cifsInodeInfo *cinode = CIFS_I(inode); 770 struct cifsInodeInfo *cinode = CIFS_I(inode);
768 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 771 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
@@ -772,7 +775,7 @@ smb_set_file_info(struct inode *inode, const char *full_path,
772 /* if the file is already open for write, just use that fileid */ 775 /* if the file is already open for write, just use that fileid */
773 open_file = find_writable_file(cinode, true); 776 open_file = find_writable_file(cinode, true);
774 if (open_file) { 777 if (open_file) {
775 netfid = open_file->fid.netfid; 778 fid.netfid = open_file->fid.netfid;
776 netpid = open_file->pid; 779 netpid = open_file->pid;
777 tcon = tlink_tcon(open_file->tlink); 780 tcon = tlink_tcon(open_file->tlink);
778 goto set_via_filehandle; 781 goto set_via_filehandle;
@@ -796,12 +799,17 @@ smb_set_file_info(struct inode *inode, const char *full_path,
796 goto out; 799 goto out;
797 } 800 }
798 801
799 cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n"); 802 oparms.tcon = tcon;
800 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, 803 oparms.cifs_sb = cifs_sb;
801 SYNCHRONIZE | FILE_WRITE_ATTRIBUTES, CREATE_NOT_DIR, 804 oparms.desired_access = SYNCHRONIZE | FILE_WRITE_ATTRIBUTES;
802 &netfid, &oplock, NULL, cifs_sb->local_nls, 805 oparms.create_options = CREATE_NOT_DIR;
803 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 806 oparms.disposition = FILE_OPEN;
807 oparms.path = full_path;
808 oparms.fid = &fid;
809 oparms.reconnect = false;
804 810
811 cifs_dbg(FYI, "calling SetFileInfo since SetPathInfo for times not supported by this server\n");
812 rc = CIFS_open(xid, &oparms, &oplock, NULL);
805 if (rc != 0) { 813 if (rc != 0) {
806 if (rc == -EIO) 814 if (rc == -EIO)
807 rc = -EINVAL; 815 rc = -EINVAL;
@@ -811,12 +819,12 @@ smb_set_file_info(struct inode *inode, const char *full_path,
811 netpid = current->tgid; 819 netpid = current->tgid;
812 820
813set_via_filehandle: 821set_via_filehandle:
814 rc = CIFSSMBSetFileInfo(xid, tcon, buf, netfid, netpid); 822 rc = CIFSSMBSetFileInfo(xid, tcon, buf, fid.netfid, netpid);
815 if (!rc) 823 if (!rc)
816 cinode->cifsAttrs = le32_to_cpu(buf->Attributes); 824 cinode->cifsAttrs = le32_to_cpu(buf->Attributes);
817 825
818 if (open_file == NULL) 826 if (open_file == NULL)
819 CIFSSMBClose(xid, tcon, netfid); 827 CIFSSMBClose(xid, tcon, fid.netfid);
820 else 828 else
821 cifsFileInfo_put(open_file); 829 cifsFileInfo_put(open_file);
822out: 830out:
@@ -908,33 +916,80 @@ cifs_mand_lock(const unsigned int xid, struct cifsFileInfo *cfile, __u64 offset,
908} 916}
909 917
910static int 918static int
919cifs_unix_dfs_readlink(const unsigned int xid, struct cifs_tcon *tcon,
920 const unsigned char *searchName, char **symlinkinfo,
921 const struct nls_table *nls_codepage)
922{
923#ifdef CONFIG_CIFS_DFS_UPCALL
924 int rc;
925 unsigned int num_referrals = 0;
926 struct dfs_info3_param *referrals = NULL;
927
928 rc = get_dfs_path(xid, tcon->ses, searchName, nls_codepage,
929 &num_referrals, &referrals, 0);
930
931 if (!rc && num_referrals > 0) {
932 *symlinkinfo = kstrndup(referrals->node_name,
933 strlen(referrals->node_name),
934 GFP_KERNEL);
935 if (!*symlinkinfo)
936 rc = -ENOMEM;
937 free_dfs_info_array(referrals, num_referrals);
938 }
939 return rc;
940#else /* No DFS support */
941 return -EREMOTE;
942#endif
943}
944
945static int
911cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, 946cifs_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
912 const char *full_path, char **target_path, 947 const char *full_path, char **target_path,
913 struct cifs_sb_info *cifs_sb) 948 struct cifs_sb_info *cifs_sb)
914{ 949{
915 int rc; 950 int rc;
916 int oplock = 0; 951 int oplock = 0;
917 __u16 netfid; 952 struct cifs_fid fid;
953 struct cifs_open_parms oparms;
918 954
919 cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path); 955 cifs_dbg(FYI, "%s: path: %s\n", __func__, full_path);
920 956
921 rc = CIFSSMBOpen(xid, tcon, full_path, FILE_OPEN, 957 /* Check for unix extensions */
922 FILE_READ_ATTRIBUTES, OPEN_REPARSE_POINT, &netfid, 958 if (cap_unix(tcon->ses)) {
923 &oplock, NULL, cifs_sb->local_nls, 959 rc = CIFSSMBUnixQuerySymLink(xid, tcon, full_path, target_path,
924 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 960 cifs_sb->local_nls);
961 if (rc == -EREMOTE)
962 rc = cifs_unix_dfs_readlink(xid, tcon, full_path,
963 target_path,
964 cifs_sb->local_nls);
965
966 goto out;
967 }
968
969 oparms.tcon = tcon;
970 oparms.cifs_sb = cifs_sb;
971 oparms.desired_access = FILE_READ_ATTRIBUTES;
972 oparms.create_options = OPEN_REPARSE_POINT;
973 oparms.disposition = FILE_OPEN;
974 oparms.path = full_path;
975 oparms.fid = &fid;
976 oparms.reconnect = false;
977
978 rc = CIFS_open(xid, &oparms, &oplock, NULL);
925 if (rc) 979 if (rc)
926 return rc; 980 goto out;
927 981
928 rc = CIFSSMBQuerySymLink(xid, tcon, netfid, target_path, 982 rc = CIFSSMBQuerySymLink(xid, tcon, fid.netfid, target_path,
929 cifs_sb->local_nls); 983 cifs_sb->local_nls);
930 if (rc) { 984 if (rc)
931 CIFSSMBClose(xid, tcon, netfid); 985 goto out_close;
932 return rc;
933 }
934 986
935 convert_delimiter(*target_path, '/'); 987 convert_delimiter(*target_path, '/');
936 CIFSSMBClose(xid, tcon, netfid); 988out_close:
937 cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path); 989 CIFSSMBClose(xid, tcon, fid.netfid);
990out:
991 if (!rc)
992 cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
938 return rc; 993 return rc;
939} 994}
940 995
@@ -1009,7 +1064,8 @@ struct smb_version_operations smb1_operations = {
1009 .mand_lock = cifs_mand_lock, 1064 .mand_lock = cifs_mand_lock,
1010 .mand_unlock_range = cifs_unlock_range, 1065 .mand_unlock_range = cifs_unlock_range,
1011 .push_mand_locks = cifs_push_mandatory_locks, 1066 .push_mand_locks = cifs_push_mandatory_locks,
1012 .query_mf_symlink = open_query_close_cifs_symlink, 1067 .query_mf_symlink = cifs_query_mf_symlink,
1068 .create_mf_symlink = cifs_create_mf_symlink,
1013 .is_read_op = cifs_is_read_op, 1069 .is_read_op = cifs_is_read_op,
1014}; 1070};
1015 1071
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 09afda4cc58e..95c43bb20335 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -82,9 +82,11 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
82 goto remove_ea_exit; 82 goto remove_ea_exit;
83 83
84 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ 84 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
85 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL, 85 if (pTcon->ses->server->ops->set_EA)
86 (__u16)0, cifs_sb->local_nls, 86 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
87 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 87 full_path, ea_name, NULL, (__u16)0,
88 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
89 CIFS_MOUNT_MAP_SPECIAL_CHR);
88 } 90 }
89remove_ea_exit: 91remove_ea_exit:
90 kfree(full_path); 92 kfree(full_path);
@@ -149,18 +151,22 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
149 cifs_dbg(FYI, "attempt to set cifs inode metadata\n"); 151 cifs_dbg(FYI, "attempt to set cifs inode metadata\n");
150 152
151 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ 153 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
152 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, 154 if (pTcon->ses->server->ops->set_EA)
153 (__u16)value_size, cifs_sb->local_nls, 155 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
154 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 156 full_path, ea_name, ea_value, (__u16)value_size,
157 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
158 CIFS_MOUNT_MAP_SPECIAL_CHR);
155 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) 159 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)
156 == 0) { 160 == 0) {
157 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 161 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
158 goto set_ea_exit; 162 goto set_ea_exit;
159 163
160 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ 164 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
161 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, 165 if (pTcon->ses->server->ops->set_EA)
162 (__u16)value_size, cifs_sb->local_nls, 166 rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
163 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 167 full_path, ea_name, ea_value, (__u16)value_size,
168 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
169 CIFS_MOUNT_MAP_SPECIAL_CHR);
164 } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, 170 } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL,
165 strlen(CIFS_XATTR_CIFS_ACL)) == 0) { 171 strlen(CIFS_XATTR_CIFS_ACL)) == 0) {
166#ifdef CONFIG_CIFS_ACL 172#ifdef CONFIG_CIFS_ACL
@@ -272,17 +278,21 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
272 /* revalidate/getattr then populate from inode */ 278 /* revalidate/getattr then populate from inode */
273 } /* BB add else when above is implemented */ 279 } /* BB add else when above is implemented */
274 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ 280 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
275 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, 281 if (pTcon->ses->server->ops->query_all_EAs)
276 buf_size, cifs_sb->local_nls, 282 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
277 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 283 full_path, ea_name, ea_value, buf_size,
284 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
285 CIFS_MOUNT_MAP_SPECIAL_CHR);
278 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { 286 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
279 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 287 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
280 goto get_ea_exit; 288 goto get_ea_exit;
281 289
282 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ 290 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
283 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, 291 if (pTcon->ses->server->ops->query_all_EAs)
284 buf_size, cifs_sb->local_nls, 292 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
285 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 293 full_path, ea_name, ea_value, buf_size,
294 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
295 CIFS_MOUNT_MAP_SPECIAL_CHR);
286 } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, 296 } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS,
287 strlen(POSIX_ACL_XATTR_ACCESS)) == 0) { 297 strlen(POSIX_ACL_XATTR_ACCESS)) == 0) {
288#ifdef CONFIG_CIFS_POSIX 298#ifdef CONFIG_CIFS_POSIX
@@ -400,11 +410,12 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
400 /* if proc/fs/cifs/streamstoxattr is set then 410 /* if proc/fs/cifs/streamstoxattr is set then
401 search server for EAs or streams to 411 search server for EAs or streams to
402 returns as xattrs */ 412 returns as xattrs */
403 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data,
404 buf_size, cifs_sb->local_nls,
405 cifs_sb->mnt_cifs_flags &
406 CIFS_MOUNT_MAP_SPECIAL_CHR);
407 413
414 if (pTcon->ses->server->ops->query_all_EAs)
415 rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
416 full_path, NULL, data, buf_size,
417 cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
418 CIFS_MOUNT_MAP_SPECIAL_CHR);
408list_ea_exit: 419list_ea_exit:
409 kfree(full_path); 420 kfree(full_path);
410 free_xid(xid); 421 free_xid(xid);