aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsglob.h4
-rw-r--r--fs/cifs/connect.c16
-rw-r--r--fs/cifs/dir.c22
-rw-r--r--fs/cifs/file.c6
-rw-r--r--fs/cifs/inode.c15
-rw-r--r--fs/cifs/smb1ops.c8
-rw-r--r--fs/cifs/smb2ops.c12
-rw-r--r--fs/cifs/smb2pdu.c2
8 files changed, 55 insertions, 30 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 25b8392bfdd2..dae7e3709cc6 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -323,11 +323,11 @@ struct smb_version_operations {
323 int (*async_writev)(struct cifs_writedata *, 323 int (*async_writev)(struct cifs_writedata *,
324 void (*release)(struct kref *)); 324 void (*release)(struct kref *));
325 /* sync read from the server */ 325 /* sync read from the server */
326 int (*sync_read)(const unsigned int, struct cifsFileInfo *, 326 int (*sync_read)(const unsigned int, struct cifs_fid *,
327 struct cifs_io_parms *, unsigned int *, char **, 327 struct cifs_io_parms *, unsigned int *, char **,
328 int *); 328 int *);
329 /* sync write to the server */ 329 /* sync write to the server */
330 int (*sync_write)(const unsigned int, struct cifsFileInfo *, 330 int (*sync_write)(const unsigned int, struct cifs_fid *,
331 struct cifs_io_parms *, unsigned int *, struct kvec *, 331 struct cifs_io_parms *, unsigned int *, struct kvec *,
332 unsigned long); 332 unsigned long);
333 /* open dir, start readdir */ 333 /* open dir, start readdir */
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 239e1fb33000..d8eb6a74b211 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -3239,10 +3239,20 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
3239 } 3239 }
3240 if (pvolume_info->mfsymlinks) { 3240 if (pvolume_info->mfsymlinks) {
3241 if (pvolume_info->sfu_emul) { 3241 if (pvolume_info->sfu_emul) {
3242 cifs_dbg(VFS, "mount option mfsymlinks ignored if sfu mount option is used\n"); 3242 /*
3243 } else { 3243 * Our SFU ("Services for Unix" emulation does not allow
3244 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS; 3244 * creating symlinks but does allow reading existing SFU
3245 * symlinks (it does allow both creating and reading SFU
3246 * style mknod and FIFOs though). When "mfsymlinks" and
3247 * "sfu" are both enabled at the same time, it allows
3248 * reading both types of symlinks, but will only create
3249 * them with mfsymlinks format. This allows better
3250 * Apple compatibility (probably better for Samba too)
3251 * while still recognizing old Windows style symlinks.
3252 */
3253 cifs_dbg(VFS, "mount options mfsymlinks and sfu both enabled\n");
3245 } 3254 }
3255 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_MF_SYMLINKS;
3246 } 3256 }
3247 3257
3248 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm)) 3258 if ((pvolume_info->cifs_acl) && (pvolume_info->dynperm))
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 073640675a39..b72bc29cba23 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -577,12 +577,13 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
577 struct cifs_io_parms io_parms; 577 struct cifs_io_parms io_parms;
578 char *full_path = NULL; 578 char *full_path = NULL;
579 struct inode *newinode = NULL; 579 struct inode *newinode = NULL;
580 int oplock = 0; 580 __u32 oplock = 0;
581 struct cifs_fid fid; 581 struct cifs_fid fid;
582 struct cifs_open_parms oparms; 582 struct cifs_open_parms oparms;
583 FILE_ALL_INFO *buf = NULL; 583 FILE_ALL_INFO *buf = NULL;
584 unsigned int bytes_written; 584 unsigned int bytes_written;
585 struct win_dev *pdev; 585 struct win_dev *pdev;
586 struct kvec iov[2];
586 587
587 if (!old_valid_dev(device_number)) 588 if (!old_valid_dev(device_number))
588 return -EINVAL; 589 return -EINVAL;
@@ -658,7 +659,11 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
658 oparms.fid = &fid; 659 oparms.fid = &fid;
659 oparms.reconnect = false; 660 oparms.reconnect = false;
660 661
661 rc = CIFS_open(xid, &oparms, &oplock, buf); 662 if (tcon->ses->server->oplocks)
663 oplock = REQ_OPLOCK;
664 else
665 oplock = 0;
666 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, buf);
662 if (rc) 667 if (rc)
663 goto mknod_out; 668 goto mknod_out;
664 669
@@ -668,25 +673,26 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
668 */ 673 */
669 674
670 pdev = (struct win_dev *)buf; 675 pdev = (struct win_dev *)buf;
671 io_parms.netfid = fid.netfid;
672 io_parms.pid = current->tgid; 676 io_parms.pid = current->tgid;
673 io_parms.tcon = tcon; 677 io_parms.tcon = tcon;
674 io_parms.offset = 0; 678 io_parms.offset = 0;
675 io_parms.length = sizeof(struct win_dev); 679 io_parms.length = sizeof(struct win_dev);
680 iov[1].iov_base = buf;
681 iov[1].iov_len = sizeof(struct win_dev);
676 if (S_ISCHR(mode)) { 682 if (S_ISCHR(mode)) {
677 memcpy(pdev->type, "IntxCHR", 8); 683 memcpy(pdev->type, "IntxCHR", 8);
678 pdev->major = cpu_to_le64(MAJOR(device_number)); 684 pdev->major = cpu_to_le64(MAJOR(device_number));
679 pdev->minor = cpu_to_le64(MINOR(device_number)); 685 pdev->minor = cpu_to_le64(MINOR(device_number));
680 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, 686 rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
681 NULL, 0); 687 &bytes_written, iov, 1);
682 } else if (S_ISBLK(mode)) { 688 } else if (S_ISBLK(mode)) {
683 memcpy(pdev->type, "IntxBLK", 8); 689 memcpy(pdev->type, "IntxBLK", 8);
684 pdev->major = cpu_to_le64(MAJOR(device_number)); 690 pdev->major = cpu_to_le64(MAJOR(device_number));
685 pdev->minor = cpu_to_le64(MINOR(device_number)); 691 pdev->minor = cpu_to_le64(MINOR(device_number));
686 rc = CIFSSMBWrite(xid, &io_parms, &bytes_written, (char *)pdev, 692 rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms,
687 NULL, 0); 693 &bytes_written, iov, 1);
688 } /* else if (S_ISFIFO) */ 694 } /* else if (S_ISFIFO) */
689 CIFSSMBClose(xid, tcon, fid.netfid); 695 tcon->ses->server->ops->close(xid, tcon, &fid);
690 d_drop(direntry); 696 d_drop(direntry);
691 697
692 /* FIXME: add code here to set EAs */ 698 /* FIXME: add code here to set EAs */
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 8f7b40fd8f3b..3e4d00a06c44 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1687,8 +1687,8 @@ cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data,
1687 io_parms.tcon = tcon; 1687 io_parms.tcon = tcon;
1688 io_parms.offset = *offset; 1688 io_parms.offset = *offset;
1689 io_parms.length = len; 1689 io_parms.length = len;
1690 rc = server->ops->sync_write(xid, open_file, &io_parms, 1690 rc = server->ops->sync_write(xid, &open_file->fid,
1691 &bytes_written, iov, 1); 1691 &io_parms, &bytes_written, iov, 1);
1692 } 1692 }
1693 if (rc || (bytes_written == 0)) { 1693 if (rc || (bytes_written == 0)) {
1694 if (total_written) 1694 if (total_written)
@@ -3206,7 +3206,7 @@ cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset)
3206 io_parms.tcon = tcon; 3206 io_parms.tcon = tcon;
3207 io_parms.offset = *offset; 3207 io_parms.offset = *offset;
3208 io_parms.length = current_read_size; 3208 io_parms.length = current_read_size;
3209 rc = server->ops->sync_read(xid, open_file, &io_parms, 3209 rc = server->ops->sync_read(xid, &open_file->fid, &io_parms,
3210 &bytes_read, &cur_offset, 3210 &bytes_read, &cur_offset,
3211 &buf_type); 3211 &buf_type);
3212 } while (rc == -EAGAIN); 3212 } while (rc == -EAGAIN);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 8fd4ee8e07ff..4ff36ea8c693 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -412,7 +412,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
412 struct cifs_sb_info *cifs_sb, unsigned int xid) 412 struct cifs_sb_info *cifs_sb, unsigned int xid)
413{ 413{
414 int rc; 414 int rc;
415 int oplock = 0; 415 __u32 oplock;
416 struct tcon_link *tlink; 416 struct tcon_link *tlink;
417 struct cifs_tcon *tcon; 417 struct cifs_tcon *tcon;
418 struct cifs_fid fid; 418 struct cifs_fid fid;
@@ -451,8 +451,13 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
451 oparms.fid = &fid; 451 oparms.fid = &fid;
452 oparms.reconnect = false; 452 oparms.reconnect = false;
453 453
454 rc = CIFS_open(xid, &oparms, &oplock, NULL); 454 if (tcon->ses->server->oplocks)
455 oplock = REQ_OPLOCK;
456 else
457 oplock = 0;
458 rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, NULL);
455 if (rc) { 459 if (rc) {
460 cifs_dbg(FYI, "check sfu type of %s, open rc = %d\n", path, rc);
456 cifs_put_tlink(tlink); 461 cifs_put_tlink(tlink);
457 return rc; 462 return rc;
458 } 463 }
@@ -464,7 +469,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
464 io_parms.offset = 0; 469 io_parms.offset = 0;
465 io_parms.length = 24; 470 io_parms.length = 24;
466 471
467 rc = CIFSSMBRead(xid, &io_parms, &bytes_read, &pbuf, &buf_type); 472 rc = tcon->ses->server->ops->sync_read(xid, &fid, &io_parms,
473 &bytes_read, &pbuf, &buf_type);
468 if ((rc == 0) && (bytes_read >= 8)) { 474 if ((rc == 0) && (bytes_read >= 8)) {
469 if (memcmp("IntxBLK", pbuf, 8) == 0) { 475 if (memcmp("IntxBLK", pbuf, 8) == 0) {
470 cifs_dbg(FYI, "Block device\n"); 476 cifs_dbg(FYI, "Block device\n");
@@ -504,7 +510,8 @@ cifs_sfu_type(struct cifs_fattr *fattr, const char *path,
504 fattr->cf_dtype = DT_REG; 510 fattr->cf_dtype = DT_REG;
505 rc = -EOPNOTSUPP; /* or some unknown SFU type */ 511 rc = -EOPNOTSUPP; /* or some unknown SFU type */
506 } 512 }
507 CIFSSMBClose(xid, tcon, fid.netfid); 513
514 tcon->ses->server->ops->close(xid, tcon, &fid);
508 cifs_put_tlink(tlink); 515 cifs_put_tlink(tlink);
509 return rc; 516 return rc;
510} 517}
diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c
index 52131d8cb4d5..2aca620193cd 100644
--- a/fs/cifs/smb1ops.c
+++ b/fs/cifs/smb1ops.c
@@ -749,21 +749,21 @@ cifs_flush_file(const unsigned int xid, struct cifs_tcon *tcon,
749} 749}
750 750
751static int 751static int
752cifs_sync_read(const unsigned int xid, struct cifsFileInfo *cfile, 752cifs_sync_read(const unsigned int xid, struct cifs_fid *pfid,
753 struct cifs_io_parms *parms, unsigned int *bytes_read, 753 struct cifs_io_parms *parms, unsigned int *bytes_read,
754 char **buf, int *buf_type) 754 char **buf, int *buf_type)
755{ 755{
756 parms->netfid = cfile->fid.netfid; 756 parms->netfid = pfid->netfid;
757 return CIFSSMBRead(xid, parms, bytes_read, buf, buf_type); 757 return CIFSSMBRead(xid, parms, bytes_read, buf, buf_type);
758} 758}
759 759
760static int 760static int
761cifs_sync_write(const unsigned int xid, struct cifsFileInfo *cfile, 761cifs_sync_write(const unsigned int xid, struct cifs_fid *pfid,
762 struct cifs_io_parms *parms, unsigned int *written, 762 struct cifs_io_parms *parms, unsigned int *written,
763 struct kvec *iov, unsigned long nr_segs) 763 struct kvec *iov, unsigned long nr_segs)
764{ 764{
765 765
766 parms->netfid = cfile->fid.netfid; 766 parms->netfid = pfid->netfid;
767 return CIFSSMBWrite2(xid, parms, written, iov, nr_segs); 767 return CIFSSMBWrite2(xid, parms, written, iov, nr_segs);
768} 768}
769 769
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index f522193b7184..ea158c9dea15 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -711,23 +711,23 @@ smb2_read_data_length(char *buf)
711 711
712 712
713static int 713static int
714smb2_sync_read(const unsigned int xid, struct cifsFileInfo *cfile, 714smb2_sync_read(const unsigned int xid, struct cifs_fid *pfid,
715 struct cifs_io_parms *parms, unsigned int *bytes_read, 715 struct cifs_io_parms *parms, unsigned int *bytes_read,
716 char **buf, int *buf_type) 716 char **buf, int *buf_type)
717{ 717{
718 parms->persistent_fid = cfile->fid.persistent_fid; 718 parms->persistent_fid = pfid->persistent_fid;
719 parms->volatile_fid = cfile->fid.volatile_fid; 719 parms->volatile_fid = pfid->volatile_fid;
720 return SMB2_read(xid, parms, bytes_read, buf, buf_type); 720 return SMB2_read(xid, parms, bytes_read, buf, buf_type);
721} 721}
722 722
723static int 723static int
724smb2_sync_write(const unsigned int xid, struct cifsFileInfo *cfile, 724smb2_sync_write(const unsigned int xid, struct cifs_fid *pfid,
725 struct cifs_io_parms *parms, unsigned int *written, 725 struct cifs_io_parms *parms, unsigned int *written,
726 struct kvec *iov, unsigned long nr_segs) 726 struct kvec *iov, unsigned long nr_segs)
727{ 727{
728 728
729 parms->persistent_fid = cfile->fid.persistent_fid; 729 parms->persistent_fid = pfid->persistent_fid;
730 parms->volatile_fid = cfile->fid.volatile_fid; 730 parms->volatile_fid = pfid->volatile_fid;
731 return SMB2_write(xid, parms, written, iov, nr_segs); 731 return SMB2_write(xid, parms, written, iov, nr_segs);
732} 732}
733 733
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 74b3a6684383..8f1672bb82d5 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1098,6 +1098,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
1098 1098
1099 if (oparms->create_options & CREATE_OPTION_READONLY) 1099 if (oparms->create_options & CREATE_OPTION_READONLY)
1100 file_attributes |= ATTR_READONLY; 1100 file_attributes |= ATTR_READONLY;
1101 if (oparms->create_options & CREATE_OPTION_SPECIAL)
1102 file_attributes |= ATTR_SYSTEM;
1101 1103
1102 req->ImpersonationLevel = IL_IMPERSONATION; 1104 req->ImpersonationLevel = IL_IMPERSONATION;
1103 req->DesiredAccess = cpu_to_le32(oparms->desired_access); 1105 req->DesiredAccess = cpu_to_le32(oparms->desired_access);