Re: [linux-cifs-client] review 5, was Re: projected date for mount.cifs to support DFS junction points

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Steve,

Looked through inode.c code again and rewrote/simplified patch5 
See attachment for it.


Q (Igor Mammedov) wrote:
> Sorry guys, but I have a lot of work for the last 3 weeks,
> so I couldn't spare much time for a hobby and react quickly.
> 
 > Also I noticed that patch 2/5 is not completely applied yet. I'll send Steve
> interim patch I've made to make thing compiled and working.
> 
> Christoph Hellwig wrote:
>> +#ifdef CONFIG_CIFS_DFS_UPCALL
>> +			if (is_remote) {
>> +				inode->i_op =
>> +					&cifs_dfs_referral_inode_operations;
>> +				inode->i_fop = NULL;
>>
>> i_fop should never be set to NULL.  Just leave it alone so it stays
>> at &empty_fops.
>>
>> +#ifdef CONFIG_CIFS_DFS_UPCALL
>> +			if (is_remote) {
>> +				inode->i_op =
>> +					&cifs_dfs_referral_inode_operations;
>> +				inode->i_fop = NULL;
>> +			} else {
>> +				inode->i_op = &cifs_dir_inode_ops;
>> +				inode->i_fop = &cifs_dir_ops;
>> +			}
>> +#else
>>  			inode->i_op = &cifs_dir_inode_ops;
>>  			inode->i_fop = &cifs_dir_ops;
>> +#endif
>>
>> This code and everything surrounding it is duplicated in two functions.
>> Please refactor it into a common helper before adding new code to it.
>>
>> _______________________________________________
>> linux-cifs-client mailing list
>> linux-cifs-client@xxxxxxxxxxxxxxx
>> https://lists.samba.org/mailman/listinfo/linux-cifs-client
>>
>> .
>>
> 
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> linux-cifs-client mailing list
> linux-cifs-client@xxxxxxxxxxxxxxx
> https://lists.samba.org/mailman/listinfo/linux-cifs-client


-- 

Best regards,

-------------------------
Igor Mammedov,
niallain "at" gmail.com




>From 03c5dcdd566f59240de7843e0a4dd3c3468a0ace Mon Sep 17 00:00:00 2001
From: Igor Mammedov <niallain@xxxxxxxxx>
Date: Tue, 4 Mar 2008 15:12:27 +0300
Subject: [PATCH] DFS patch that connects inode with dfs handling ops
  if it is DFS junction point.

Signed-off-by: Igor Mammedov <niallain@xxxxxxxxx>
---
 fs/cifs/inode.c |  134 ++++++++++++++++++++++++++++++------------------------
 1 files changed, 74 insertions(+), 60 deletions(-)

diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 24eb4d3..7f501e4 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -29,8 +29,9 @@
 #include "cifs_debug.h"
 #include "cifs_fs_sb.h"
 
-
-static void cifs_set_ops(struct inode *inode)
+#define PATH_IN_DFS 1
+#define PATH_NOT_IN_DFS 0
+static void cifs_set_ops(const int in_dfs, struct inode *inode)
 {
 	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
@@ -57,8 +58,12 @@ static void cifs_set_ops(struct inode *inode)
 			inode->i_data.a_ops = &cifs_addr_ops;
 		break;
 	case S_IFDIR:
-		inode->i_op = &cifs_dir_inode_ops;
-		inode->i_fop = &cifs_dir_ops;
+		if (in_dfs == PATH_IN_DFS) {
+			inode->i_op = &cifs_dfs_referral_inode_operations;
+		} else {
+			inode->i_op = &cifs_dir_inode_ops;
+			inode->i_fop = &cifs_dir_ops;
+		}
 		break;
 	case S_IFLNK:
 		inode->i_op = &cifs_symlink_inode_ops;
@@ -153,6 +158,30 @@ static void cifs_unix_info_to_inode(struct inode *inode,
 	spin_unlock(&inode->i_lock);
 }
 
+static const unsigned char *cifs_get_search_path(struct cifsTconInfo *pTcon,
+					const char *search_path)
+{
+	int tree_len;
+	int path_len;
+	char *tmp_path;
+
+	if (!(pTcon->Flags & SMB_SHARE_IS_IN_DFS))
+		return search_path;
+
+	/* use full path name for working with DFS */
+	tree_len = strnlen(pTcon->treeName, MAX_TREE_SIZE + 1);
+	path_len = strnlen(search_path, MAX_PATHCONF);
+
+	tmp_path = kmalloc(tree_len+path_len+1, GFP_KERNEL);
+	if (tmp_path == NULL)
+		return search_path;
+
+	strncpy(tmp_path, pTcon->treeName, tree_len);
+	strncpy(tmp_path+tree_len, search_path, path_len);
+	tmp_path[tree_len+path_len] = 0;
+	return tmp_path;
+}
+
 int cifs_get_inode_info_unix(struct inode **pinode,
 	const unsigned char *search_path, struct super_block *sb, int xid)
 {
@@ -161,41 +190,31 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 	struct cifsTconInfo *pTcon;
 	struct inode *inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	char *tmp_path;
+	const char *tmp_path = NULL;
+	const unsigned char *full_path;
+	int in_dfs = PATH_NOT_IN_DFS;
 
 	pTcon = cifs_sb->tcon;
 	cFYI(1, ("Getting info on %s", search_path));
+
+	full_path = cifs_get_search_path(pTcon, search_path);
+	tmp_path = full_path != search_path?full_path:NULL;
+
+try_again_CIFSSMBUnixQPathInfo:
 	/* could have done a find first instead but this returns more info */
-	rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
+	rc = CIFSSMBUnixQPathInfo(xid, pTcon, full_path, &findData,
 				  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
 					CIFS_MOUNT_MAP_SPECIAL_CHR);
 /*	dump_mem("\nUnixQPathInfo return data", &findData,
 		 sizeof(findData)); */
 	if (rc) {
-		if (rc == -EREMOTE) {
-			tmp_path =
-			    kmalloc(strnlen(pTcon->treeName,
-					    MAX_TREE_SIZE + 1) +
-				    strnlen(search_path, MAX_PATHCONF) + 1,
-				    GFP_KERNEL);
-			if (tmp_path == NULL)
-				return -ENOMEM;
-
-			/* have to skip first of the double backslash of
-			   UNC name */
-			strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
-			strncat(tmp_path, search_path, MAX_PATHCONF);
-			rc = connect_to_dfs_path(xid, pTcon->ses,
-						 /* treename + */ tmp_path,
-						 cifs_sb->local_nls,
-						 cifs_sb->mnt_cifs_flags &
-						    CIFS_MOUNT_MAP_SPECIAL_CHR);
-			kfree(tmp_path);
-
-			/* BB fix up inode etc. */
-		} else if (rc) {
-			return rc;
+		if ((rc == -EREMOTE) && (in_dfs == PATH_NOT_IN_DFS)) {
+			in_dfs = PATH_IN_DFS;
+			full_path = search_path;
+			goto try_again_CIFSSMBUnixQPathInfo;
 		}
+		kfree(tmp_path);
+		return rc;
 	} else {
 		struct cifsInodeInfo *cifsInfo;
 		__u64 num_of_bytes = le64_to_cpu(findData.NumOfBytes);
@@ -204,8 +223,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 		/* get new inode */
 		if (*pinode == NULL) {
 			*pinode = new_inode(sb);
-			if (*pinode == NULL)
+			if (*pinode == NULL) {
+				kfree(tmp_path);
 				return -ENOMEM;
+			}
 			/* Is an i_ino of zero legal? */
 			/* Are there sanity checks we can use to ensure that
 			   the server is really filling in that field? */
@@ -237,8 +258,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 			(unsigned long) inode->i_size,
 			(unsigned long long)inode->i_blocks));
 
-		cifs_set_ops(inode);
+		cifs_set_ops(in_dfs, inode);
 	}
+	kfree(tmp_path);
 	return rc;
 }
 
@@ -353,9 +375,11 @@ int cifs_get_inode_info(struct inode **pinode,
 	struct cifsTconInfo *pTcon;
 	struct inode *inode;
 	struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
-	char *tmp_path;
+	const char *tmp_path = NULL;
+	const unsigned char *full_path;
 	char *buf = NULL;
 	int adjustTZ = FALSE;
+	int in_dfs = PATH_NOT_IN_DFS;
 
 	pTcon = cifs_sb->tcon;
 	cFYI(1, ("Getting info on %s", search_path));
@@ -373,8 +397,13 @@ int cifs_get_inode_info(struct inode **pinode,
 		if (buf == NULL)
 			return -ENOMEM;
 		pfindData = (FILE_ALL_INFO *)buf;
+
+		full_path = cifs_get_search_path(pTcon, search_path);
+		tmp_path = full_path != search_path?full_path:NULL;
+
+try_again_CIFSSMBQPathInfo:
 		/* could do find first instead but this returns more info */
-		rc = CIFSSMBQPathInfo(xid, pTcon, search_path, pfindData,
+		rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
 			      0 /* not legacy */,
 			      cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
 				CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -382,7 +411,7 @@ int cifs_get_inode_info(struct inode **pinode,
 		when server claims no NT SMB support and the above call
 		failed at least once - set flag in tcon or mount */
 		if ((rc == -EOPNOTSUPP) || (rc == -EINVAL)) {
-			rc = SMBQueryInformation(xid, pTcon, search_path,
+			rc = SMBQueryInformation(xid, pTcon, full_path,
 					pfindData, cifs_sb->local_nls,
 					cifs_sb->mnt_cifs_flags &
 					  CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -391,31 +420,14 @@ int cifs_get_inode_info(struct inode **pinode,
 	}
 	/* dump_mem("\nQPathInfo return data",&findData, sizeof(findData)); */
 	if (rc) {
-		if (rc == -EREMOTE) {
-			tmp_path =
-			    kmalloc(strnlen
-				    (pTcon->treeName,
-				     MAX_TREE_SIZE + 1) +
-				    strnlen(search_path, MAX_PATHCONF) + 1,
-				    GFP_KERNEL);
-			if (tmp_path == NULL) {
-				kfree(buf);
-				return -ENOMEM;
-			}
-
-			strncpy(tmp_path, pTcon->treeName, MAX_TREE_SIZE);
-			strncat(tmp_path, search_path, MAX_PATHCONF);
-			rc = connect_to_dfs_path(xid, pTcon->ses,
-						 /* treename + */ tmp_path,
-						 cifs_sb->local_nls,
-						 cifs_sb->mnt_cifs_flags &
-						   CIFS_MOUNT_MAP_SPECIAL_CHR);
-			kfree(tmp_path);
-			/* BB fix up inode etc. */
-		} else if (rc) {
-			kfree(buf);
-			return rc;
+		if ((rc == -EREMOTE) && (in_dfs == PATH_NOT_IN_DFS)) {
+			in_dfs = PATH_IN_DFS;
+			full_path = search_path;
+			goto try_again_CIFSSMBQPathInfo;
 		}
+		kfree(tmp_path);
+		kfree(buf);
+		return rc;
 	} else {
 		struct cifsInodeInfo *cifsInfo;
 		__u32 attr = le32_to_cpu(pfindData->Attributes);
@@ -424,6 +436,7 @@ int cifs_get_inode_info(struct inode **pinode,
 		if (*pinode == NULL) {
 			*pinode = new_inode(sb);
 			if (*pinode == NULL) {
+				kfree(tmp_path);
 				kfree(buf);
 				return -ENOMEM;
 			}
@@ -573,8 +586,9 @@ int cifs_get_inode_info(struct inode **pinode,
 			atomic_set(&cifsInfo->inUse, 1);
 		}
 
-		cifs_set_ops(inode);
+		cifs_set_ops(in_dfs, inode);
 	}
+	kfree(tmp_path);
 	kfree(buf);
 	return rc;
 }
@@ -804,7 +818,7 @@ static void posix_fill_in_inode(struct inode *tmp_inode,
 	local_size  = tmp_inode->i_size;
 
 	cifs_unix_info_to_inode(tmp_inode, pData, 1);
-	cifs_set_ops(tmp_inode);
+	cifs_set_ops(PATH_NOT_IN_DFS, tmp_inode);
 
 	if (!S_ISREG(tmp_inode->i_mode))
 		return;
-- 
1.5.3.7


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux