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