Steve French wrote: > Attached is dfs path construction fixup for / character in > \\server\share component of dfs path. Let me know if you see any > problem - but it gets Samba past the problem with not returning > STATUS_PATH_NOT_COVERED > > similar change will have to be made to build_full_dfs_path_from_dentry > in cifs_dfs_ref.c > > This makes it easier for me to test the remainder of the changes > needed to the SMB GetDFSReferral function(s). Has anyone checked on > the answer to Al's question on submount expiry from a few days ago? I've just tested it and the patch fixed a problem with the lack of STATUS_PATH_NOT_COVERED with unix-ext enabled on samba server. 1. samba with unix-ext enabled returns (5th packet) dfs link as a symbolic link, but for dfs code it should be the directory type so we could fix it in the time of creating inode and get the server generated inode number. No. Time Source Destination Protocol Info 1 0.000000 192.168.133.129 192.168.133.1 SMB Trans2 Request, QUERY_PATH_INFO, Query File Unix Basic, Path: //192.168.133.1/dfs/dfs2 2 0.000385 192.168.133.1 192.168.133.129 SMB Trans2 Response, QUERY_PATH_INFO, Error: STATUS_PATH_NOT_COVERED 3 0.000670 192.168.133.129 192.168.133.1 TCP 46662 > microsoft-ds [ACK] Seq=127 Ack=40 Win=1728 Len=0 TSV=509648098 TSER=3625842022 4 0.006911 192.168.133.129 192.168.133.1 SMB Trans2 Request, QUERY_PATH_INFO, Query File Unix Basic, Path: /dfs2 5 0.007110 192.168.133.1 192.168.133.129 SMB Trans2 Response, QUERY_PATH_INFO ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - here our chance to get it working 6 0.016002 192.168.133.129 192.168.133.1 SMB Trans2 Request, QUERY_PATH_INFO, Query File Unix Link, Path: /dfs2 7 0.016219 192.168.133.1 192.168.133.129 SMB Trans2 Response, QUERY_PATH_INFO 8 0.049621 192.168.133.129 192.168.133.1 SMB Trans2 Request, QUERY_PATH_INFO, Query File Unix Basic, Path: //192.168.133.1/dfs/msdfs:\172.16.61.1\dfs2 9 0.050706 192.168.133.1 192.168.133.129 SMB Trans2 Response, QUERY_PATH_INFO, Error: STATUS_OBJECT_NAME_NOT_FOUND Patches that make dfs working in this case are attached. 2. samba with unix-ext disabled returns STATUS_OBJECT_NAME_NOT_FOUND on the second query (5th packet). Replacing '\' with '/' doesn't help. It looks we will not be able to make this case work unless we disable server generated inode numbers and fill up junction point inode with fake values. Another way to make it working is to fix samba code so that it would return inode info (with directory type) on the second call as win2k does. No. Time Source Destination Protocol Info 1 0.000000 192.168.133.129 192.168.133.1 SMB Trans2 Request, QUERY_PATH_INFO, Query File All Info, Path: \\192.168.133.1\dfs\dfs2 2 0.000576 192.168.133.1 192.168.133.129 SMB Trans2 Response, QUERY_PATH_INFO, Error: STATUS_PATH_NOT_COVERED 3 0.000746 192.168.133.129 192.168.133.1 TCP 37925 > microsoft-ds [ACK] Seq=127 Ack=40 Win=1728 Len=0 TSV=510792731 TSER=3626976733 4 0.004212 192.168.133.129 192.168.133.1 SMB Trans2 Request, QUERY_PATH_INFO, Query File All Info, Path: \dfs2 5 0.004606 192.168.133.1 192.168.133.129 SMB Trans2 Response, QUERY_PATH_INFO, Error: STATUS_OBJECT_NAME_NOT_FOUND -- Best regards, ------------------------- Igor Mammedov, niallain "at" gmail.com
>From deef01fdc817a0e0d167e28eabe30890fc789608 Mon Sep 17 00:00:00 2001 From: Igor Mammedov <niallain@xxxxxxxxx> Date: Wed, 23 Apr 2008 17:34:28 +0400 Subject: [PATCH] Adds to dns_resolver checking if the server name is an IP addr and skipping upcall in this case. Signed-off-by: Igor Mammedov <niallain@xxxxxxxxx> --- fs/cifs/dns_resolve.c | 62 +++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 52 insertions(+), 10 deletions(-) diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 7cc86c4..939e256 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c @@ -55,6 +55,32 @@ struct key_type key_type_dns_resolver = { .match = user_match, }; +/* Checks if supplied name is IP address + * returns: + * 1 - name is IP + * 0 - name is not IP + */ +static int is_ip(const char *name) +{ + int rc; + struct sockaddr_in sin_server; + struct sockaddr_in6 sin_server6; + + rc = cifs_inet_pton(AF_INET, name, + &sin_server.sin_addr.s_addr); + + if (rc <= 0) { + /* not ipv4 address, try ipv6 */ + rc = cifs_inet_pton(AF_INET6, name, + &sin_server6.sin6_addr.in6_u); + if (rc > 0) + return 1; + } else { + return 1; + } + /* we failed translating address */ + return 0; +} /* Resolves server name to ip address. * input: @@ -67,8 +93,9 @@ int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) { int rc = -EAGAIN; - struct key *rkey; + struct key *rkey = ERR_PTR(-EAGAIN); char *name; + char *data = NULL; int len; if (!ip_addr || !unc) @@ -97,26 +124,41 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) memcpy(name, unc+2, len); name[len] = 0; + if (is_ip(name)) { + cFYI(1, ("%s: it is IP, skipping dns upcall: %s", + __func__, name)); + data = name; + goto skip_upcall; + } + rkey = request_key(&key_type_dns_resolver, name, ""); if (!IS_ERR(rkey)) { - len = strlen(rkey->payload.data); - *ip_addr = kmalloc(len+1, GFP_KERNEL); - if (*ip_addr) { - memcpy(*ip_addr, rkey->payload.data, len); - (*ip_addr)[len] = '\0'; - cFYI(1, ("%s: resolved: %s to %s", __func__, + data = rkey->payload.data; + cFYI(1, ("%s: resolved: %s to %s", __func__, rkey->description, *ip_addr )); + } else { + cERROR(1, ("%s: unable to resolve: %s", __func__, name)); + goto out; + } + +skip_upcall: + if (data) { + len = strlen(data); + *ip_addr = kmalloc(len+1, GFP_KERNEL); + if (*ip_addr) { + memcpy(*ip_addr, data, len); + (*ip_addr)[len] = '\0'; rc = 0; } else { rc = -ENOMEM; } - key_put(rkey); - } else { - cERROR(1, ("%s: unable to resolve: %s", __func__, name)); + if (!IS_ERR(rkey)) + key_put(rkey); } +out: kfree(name); return rc; } -- 1.5.3.7
>From d69f4d0a59086658491eec4f2e43a890c4357a29 Mon Sep 17 00:00:00 2001 From: Igor Mammedov <niallain@xxxxxxxxx> Date: Wed, 23 Apr 2008 17:40:34 +0400 Subject: [PATCH] fixed compatibility issue with samba: a refferal request UNC is canonized to '/' path separator Signed-off-by: Igor Mammedov <niallain@xxxxxxxxx> --- fs/cifs/cifs_dfs_ref.c | 23 +++++++++++++---------- 1 files changed, 13 insertions(+), 10 deletions(-) diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index f53f41f..bc110f7 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -81,15 +81,11 @@ static char *cifs_get_share_name(const char *node_name) /* find sharename end */ pSep++; pSep = memchr(UNC+(pSep-UNC), '\\', len-(pSep-UNC)); - if (!pSep) { - cERROR(1, ("%s:2 cant find share name in node name: %s", - __func__, node_name)); - kfree(UNC); - return NULL; + if (pSep) { + /* trim path up to sharename end + * now we have share name in UNC */ + *pSep = 0; } - /* trim path up to sharename end - * * now we have share name in UNC */ - *pSep = 0; return UNC; } @@ -176,7 +172,7 @@ static char *compose_mount_options(const char *sb_mountdata, tkn_e = strchr(tkn_e+1, '\\'); if (tkn_e) { strcat(mountdata, ",prefixpath="); - strcat(mountdata, tkn_e); + strcat(mountdata, tkn_e+1); } } @@ -232,7 +228,8 @@ static char *build_full_dfs_path_from_dentry(struct dentry *dentry) return NULL; if (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS) { - /* we should use full path name to correct working with DFS */ + int i; + /* we should use full path name for correct working with DFS */ l_max_len = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE+1) + strnlen(search_path, MAX_PATHCONF) + 1; tmp_path = kmalloc(l_max_len, GFP_KERNEL); @@ -243,6 +240,12 @@ static char *build_full_dfs_path_from_dentry(struct dentry *dentry) strncpy(tmp_path, cifs_sb->tcon->treeName, l_max_len); strcat(tmp_path, search_path); tmp_path[l_max_len-1] = 0; + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) + for (i = 0; i < l_max_len; i++) { + if (tmp_path[i] == '\\') + tmp_path[i] = '/'; + } + full_path = tmp_path; kfree(search_path); } else { -- 1.5.3.7
>From e5914b5297d953ba3d08fb79bb82e0d890130218 Mon Sep 17 00:00:00 2001 From: Igor Mammedov <niallain@xxxxxxxxx> Date: Wed, 23 Apr 2008 17:57:34 +0400 Subject: [PATCH] Workaround for working with samba (unix extentions mode enabled only). Fixup inode from symlink to directory mode, so we could mount on it a dfs submount. Since samba in unix-ext mode returns a dfs junction point as a link, we have a chance to get symlink info (including inode number) and right after that fix inode mode from symlink to directory. That looks wierd but DFS works (at least in the case when samba is in unix-ext mode).` Signed-off-by: Igor Mammedov <niallain@xxxxxxxxx> --- fs/cifs/inode.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index e1031b9..144879b 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -261,6 +261,14 @@ try_again_CIFSSMBUnixQPathInfo: cifs_unix_info_to_inode(inode, &findData, 0); + /* if it dfs link (i.e. we've got PATH_UNCOVERED error) + * we need to fix up its type to the directory before + * making it mount point */ + if (is_dfs_referral && (inode->i_mode & S_IFMT & S_IFLNK)) { + inode->i_mode &= ~S_IFLNK; + inode->i_mode |= S_IFDIR; + cFYI(1, ("faking dir type for the dfs link")); + } if (num_of_bytes < end_of_file) cFYI(1, ("allocation size less than end of file")); -- 1.5.3.7