aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorPavel Shilovsky <piastry@etersoft.ru>2013-10-23 09:49:47 -0400
committerSteve French <smfrench@gmail.com>2013-11-11 17:31:03 -0500
commiteb85d94bdd91fb4dbea4ee465d4349cbea4eaaca (patch)
tree217ed41bd6bdf55b5a7263d42ebab386f6377785 /fs/cifs/inode.c
parent6c86ae2928f9e4cbf0d5844f5fcfd549e3450b8c (diff)
CIFS: Fix symbolic links usage
Now we treat any reparse point as a symbolic link and map it to a Unix one that is not true in a common case due to many reparse point types supported by SMB servers. Distinguish reparse point types into two groups: 1) that can be accessed directly through a reparse point (junctions, deduplicated files, NFS symlinks); 2) that need to be processed manually (Windows symbolic links, DFS); and map only Windows symbolic links to Unix ones. Cc: <stable@vger.kernel.org> Acked-by: Jeff Layton <jlayton@redhat.com> Reported-and-tested-by: Joao Correia <joaomiguelcorreia@gmail.com> Signed-off-by: Pavel Shilovsky <piastry@etersoft.ru> Signed-off-by: Steve French <smfrench@gmail.com>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 867b7cdc794a..36f9ebb93ceb 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -542,7 +542,8 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
542/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */ 542/* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
543static void 543static void
544cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, 544cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
545 struct cifs_sb_info *cifs_sb, bool adjust_tz) 545 struct cifs_sb_info *cifs_sb, bool adjust_tz,
546 bool symlink)
546{ 547{
547 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 548 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
548 549
@@ -569,7 +570,11 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
569 fattr->cf_createtime = le64_to_cpu(info->CreationTime); 570 fattr->cf_createtime = le64_to_cpu(info->CreationTime);
570 571
571 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); 572 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
572 if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { 573
574 if (symlink) {
575 fattr->cf_mode = S_IFLNK;
576 fattr->cf_dtype = DT_LNK;
577 } else if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
573 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; 578 fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode;
574 fattr->cf_dtype = DT_DIR; 579 fattr->cf_dtype = DT_DIR;
575 /* 580 /*
@@ -578,10 +583,6 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
578 */ 583 */
579 if (!tcon->unix_ext) 584 if (!tcon->unix_ext)
580 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK; 585 fattr->cf_flags |= CIFS_FATTR_UNKNOWN_NLINK;
581 } else if (fattr->cf_cifsattrs & ATTR_REPARSE) {
582 fattr->cf_mode = S_IFLNK;
583 fattr->cf_dtype = DT_LNK;
584 fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks);
585 } else { 586 } else {
586 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; 587 fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode;
587 fattr->cf_dtype = DT_REG; 588 fattr->cf_dtype = DT_REG;
@@ -626,7 +627,8 @@ cifs_get_file_info(struct file *filp)
626 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data); 627 rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
627 switch (rc) { 628 switch (rc) {
628 case 0: 629 case 0:
629 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false); 630 cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false,
631 false);
630 break; 632 break;
631 case -EREMOTE: 633 case -EREMOTE:
632 cifs_create_dfs_fattr(&fattr, inode->i_sb); 634 cifs_create_dfs_fattr(&fattr, inode->i_sb);
@@ -673,6 +675,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
673 bool adjust_tz = false; 675 bool adjust_tz = false;
674 struct cifs_fattr fattr; 676 struct cifs_fattr fattr;
675 struct cifs_search_info *srchinf = NULL; 677 struct cifs_search_info *srchinf = NULL;
678 bool symlink = false;
676 679
677 tlink = cifs_sb_tlink(cifs_sb); 680 tlink = cifs_sb_tlink(cifs_sb);
678 if (IS_ERR(tlink)) 681 if (IS_ERR(tlink))
@@ -702,12 +705,12 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
702 } 705 }
703 data = (FILE_ALL_INFO *)buf; 706 data = (FILE_ALL_INFO *)buf;
704 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path, 707 rc = server->ops->query_path_info(xid, tcon, cifs_sb, full_path,
705 data, &adjust_tz); 708 data, &adjust_tz, &symlink);
706 } 709 }
707 710
708 if (!rc) { 711 if (!rc) {
709 cifs_all_info_to_fattr(&fattr, (FILE_ALL_INFO *)data, cifs_sb, 712 cifs_all_info_to_fattr(&fattr, data, cifs_sb, adjust_tz,
710 adjust_tz); 713 symlink);
711 } else if (rc == -EREMOTE) { 714 } else if (rc == -EREMOTE) {
712 cifs_create_dfs_fattr(&fattr, sb); 715 cifs_create_dfs_fattr(&fattr, sb);
713 rc = 0; 716 rc = 0;