Commit c18c842b authored by Steve French's avatar Steve French
Browse files

[CIFS] Allow disabling CIFS Unix Extensions as mount option



Previously the only way to do this was to umount all mounts to that server,
turn off a proc setting (/proc/fs/cifs/LinuxExtensionsEnabled).

Fixes Samba bugzilla bug number: 4582 (and also 2008)

Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
parent 63135e08
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -316,10 +316,10 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
			seq_printf(s, ",posixpaths");
			seq_printf(s, ",posixpaths");
		if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
		if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) ||
		   !(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
		   !(cifs_sb->tcon->unix_ext))
			seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
			seq_printf(s, ",uid=%d", cifs_sb->mnt_uid);
		if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
		if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) ||
		   !(cifs_sb->tcon->ses->capabilities & CAP_UNIX))
		   !(cifs_sb->tcon->unix_ext))
			seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
			seq_printf(s, ",gid=%d", cifs_sb->mnt_gid);
		seq_printf(s, ",rsize=%d", cifs_sb->rsize);
		seq_printf(s, ",rsize=%d", cifs_sb->rsize);
		seq_printf(s, ",wsize=%d", cifs_sb->wsize);
		seq_printf(s, ",wsize=%d", cifs_sb->wsize);
+3 −1
Original line number Original line Diff line number Diff line
@@ -281,7 +281,9 @@ struct cifsTconInfo {
	FILE_SYSTEM_UNIX_INFO fsUnixInfo;
	FILE_SYSTEM_UNIX_INFO fsUnixInfo;
	unsigned retry:1;
	unsigned retry:1;
	unsigned nocase:1;
	unsigned nocase:1;
	/* BB add field for back pointer to sb struct? */
	unsigned unix_ext:1; /* if off disable Linux extensions to CIFS protocol
				for this mount even if server would support */
	/* BB add field for back pointer to sb struct(s)? */
};
};


/*
/*
+6 −15
Original line number Original line Diff line number Diff line
@@ -3638,15 +3638,6 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
	pSMB->SearchHandle = searchHandle;      /* always kept as le */
	pSMB->SearchHandle = searchHandle;      /* always kept as le */
	pSMB->SearchCount =
	pSMB->SearchCount =
		cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
		cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
	/* test for Unix extensions */
/*	if (tcon->ses->capabilities & CAP_UNIX) {
		pSMB->InformationLevel = cpu_to_le16(SMB_FIND_FILE_UNIX);
		psrch_inf->info_level = SMB_FIND_FILE_UNIX;
	} else {
		pSMB->InformationLevel =
		   cpu_to_le16(SMB_FIND_FILE_DIRECTORY_INFO);
		psrch_inf->info_level = SMB_FIND_FILE_DIRECTORY_INFO;
	} */
	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
	pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
	pSMB->ResumeKey = psrch_inf->resume_key;
	pSMB->ResumeKey = psrch_inf->resume_key;
	pSMB->SearchFlags =
	pSMB->SearchFlags =
+24 −7
Original line number Original line Diff line number Diff line
@@ -85,6 +85,7 @@ struct smb_vol {
	unsigned direct_io:1;
	unsigned direct_io:1;
	unsigned remap:1;   /* set to remap seven reserved chars in filenames */
	unsigned remap:1;   /* set to remap seven reserved chars in filenames */
	unsigned posix_paths:1;   /* unset to not ask for posix pathnames. */
	unsigned posix_paths:1;   /* unset to not ask for posix pathnames. */
	unsigned no_linux_ext:1;
	unsigned sfu_emul:1;
	unsigned sfu_emul:1;
	unsigned nullauth:1; /* attempt to authenticate with null user */
	unsigned nullauth:1; /* attempt to authenticate with null user */
	unsigned nocase;     /* request case insensitive filenames */
	unsigned nocase;     /* request case insensitive filenames */
@@ -1192,6 +1193,10 @@ cifs_parse_mount_options(char *options, const char *devname,
			vol->posix_paths = 1;
			vol->posix_paths = 1;
		} else if (strnicmp(data, "noposixpaths", 12) == 0) {
		} else if (strnicmp(data, "noposixpaths", 12) == 0) {
			vol->posix_paths = 0;
			vol->posix_paths = 0;
		} else if (strnicmp(data, "nounix", 6) == 0) {
			vol->no_linux_ext = 1;
		} else if (strnicmp(data, "nolinux", 7) == 0) {
			vol->no_linux_ext = 1;
		} else if ((strnicmp(data, "nocase", 6) == 0) ||
		} else if ((strnicmp(data, "nocase", 6) == 0) ||
			   (strnicmp(data, "ignorecase", 10)  == 0)) {
			   (strnicmp(data, "ignorecase", 10)  == 0)) {
			vol->nocase = 1;
			vol->nocase = 1;
@@ -1665,6 +1670,18 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
	 * and once without posixacls or posix paths? */
	 * and once without posixacls or posix paths? */
	__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
	__u64 saved_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);


	if (vol_info && vol_info->no_linux_ext) {
		tcon->fsUnixInfo.Capability = 0;
		tcon->unix_ext = 0; /* Unix Extensions disabled */
		cFYI(1, ("Linux protocol extensions disabled"));
		return;
	} else if (vol_info)
		tcon->unix_ext = 1; /* Unix Extensions supported */

	if (tcon->unix_ext == 0) {
		cFYI(1, ("Unix extensions disabled so not set on reconnect"));
		return;
	}


	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
@@ -1678,10 +1695,6 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
				cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
			if ((saved_cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) == 0)
				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
				cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;




		}
		}


		cap &= CIFS_UNIX_CAP_MASK;
		cap &= CIFS_UNIX_CAP_MASK;
@@ -2176,13 +2189,17 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,


		/* tell server which Unix caps we support */
		/* tell server which Unix caps we support */
		if (tcon->ses->capabilities & CAP_UNIX)
		if (tcon->ses->capabilities & CAP_UNIX)
			/* reset of caps checks mount to see if unix extensions
			   disabled for just this mount */
			reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
			reset_cifs_unix_caps(xid, tcon, sb, &volume_info);
		else if (cifs_sb->rsize > (1024 * 127)) {
		else
			tcon->unix_ext = 0; /* server does not support them */

		if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) {
			cifs_sb->rsize = 1024 * 127;
			cifs_sb->rsize = 1024 * 127;
#ifdef CONFIG_CIFS_DEBUG2
#ifdef CONFIG_CIFS_DEBUG2
			cFYI(1, ("no very large read support, rsize 127K"));
			cFYI(1, ("no very large read support, rsize now 127K"));
#endif
#endif

		}
		}
		if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
		if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
			cifs_sb->wsize = min(cifs_sb->wsize,
			cifs_sb->wsize = min(cifs_sb->wsize,
+5 −6
Original line number Original line Diff line number Diff line
@@ -207,8 +207,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
	} else {
	} else {
		/* If Open reported that we actually created a file
		/* If Open reported that we actually created a file
		then we now have to set the mode if possible */
		then we now have to set the mode if possible */
		if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
		if ((pTcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
			(oplock & CIFS_CREATE_ACTION)) {
			mode &= ~current->fs->umask;
			mode &= ~current->fs->umask;
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
			if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
				CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
@@ -235,8 +234,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
			/* Could set r/o dos attribute if mode & 0222 == 0 */
			/* Could set r/o dos attribute if mode & 0222 == 0 */
		}
		}


	/* BB server might mask mode so we have to query for Unix case*/
		/* server might mask mode so we have to query for it */
		if (pTcon->ses->capabilities & CAP_UNIX)
		if (pTcon->unix_ext)
			rc = cifs_get_inode_info_unix(&newinode, full_path,
			rc = cifs_get_inode_info_unix(&newinode, full_path,
						 inode->i_sb, xid);
						 inode->i_sb, xid);
		else {
		else {
@@ -337,7 +336,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
	full_path = build_path_from_dentry(direntry);
	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL)
	if (full_path == NULL)
		rc = -ENOMEM;
		rc = -ENOMEM;
	else if (pTcon->ses->capabilities & CAP_UNIX) {
	else if (pTcon->unix_ext) {
		mode &= ~current->fs->umask;
		mode &= ~current->fs->umask;
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
			rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
@@ -491,7 +490,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
	cFYI(1,
	cFYI(1,
	     (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));
	     (" Full path: %s inode = 0x%p", full_path, direntry->d_inode));


	if (pTcon->ses->capabilities & CAP_UNIX)
	if (pTcon->unix_ext)
		rc = cifs_get_inode_info_unix(&newInode, full_path,
		rc = cifs_get_inode_info_unix(&newInode, full_path,
					      parent_dir_inode->i_sb, xid);
					      parent_dir_inode->i_sb, xid);
	else
	else
Loading