From: "Steve French" <smfrench@gmail.com>
To: "Q (Igor Mammedov)" <qwerty0987654321@mail.ru>,
"Igor Mammedov" <niallain@gmail.com>,
"Jeremy Allison" <jra@samba.org>,
"Jeff Layton" <jlayton@redhat.com>,
linux-cifs-client@lists.sa
Subject: dfs path construction fix - send dfs paths on all path based operations on share in dfs
Date: Tue, 13 May 2008 17:45:48 -0500 [thread overview]
Message-ID: <524f69650805131545id9be81et97549c74ecd0e7c8@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 215 bytes --]
Samba was not handling paths without the \\server\share prefix (which
our current code sends on QueryPathInfo) when "SHARE_IN_DFS" on
operations such as rmdir and delete.
This patch fixes that:
--
Thanks,
Steve
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: fix-path-requests-when-share-in-dfs.patch --]
[-- Type: text/x-diff; name=fix-path-requests-when-share-in-dfs.patch, Size: 6936 bytes --]
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index e4e0078..05afe33 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -49,18 +49,25 @@ build_path_from_dentry(struct dentry *direntry)
struct dentry *temp;
int namelen;
int pplen;
+ int dfsplen;
char *full_path;
char dirsep;
+ struct cifs_sb_info *cifs_sb;
if (direntry == NULL)
return NULL; /* not much we can do if dentry is freed and
we need to reopen the file after it was closed implicitly
when the server crashed */
- dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
- pplen = CIFS_SB(direntry->d_sb)->prepathlen;
+ cifs_sb = CIFS_SB(direntry->d_sb);
+ dirsep = CIFS_DIR_SEP(cifs_sb);
+ pplen = cifs_sb->prepathlen;
+ if (cifs_sb->tcon && (cifs_sb->tcon->Flags & SMB_SHARE_IS_IN_DFS))
+ dfsplen = strnlen(cifs_sb->tcon->treeName, MAX_TREE_SIZE + 1);
+ else
+ dfsplen = 0;
cifs_bp_rename_retry:
- namelen = pplen;
+ namelen = pplen + dfsplen;
for (temp = direntry; !IS_ROOT(temp);) {
namelen += (1 + temp->d_name.len);
temp = temp->d_parent;
@@ -91,7 +98,7 @@ cifs_bp_rename_retry:
return NULL;
}
}
- if (namelen != pplen) {
+ if (namelen != pplen + dfsplen) {
cERROR(1,
("did not end path lookup where expected namelen is %d",
namelen));
@@ -107,7 +114,18 @@ cifs_bp_rename_retry:
since the '\' is a valid posix character so we can not switch
those safely to '/' if any are found in the middle of the prepath */
/* BB test paths to Windows with '/' in the midst of prepath */
- strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen);
+
+ if (dfsplen) {
+ strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
+ int i;
+ for (i = 0; i < dfsplen; i++) {
+ if (full_path[i] == '\\')
+ full_path[i] = '/';
+ }
+ }
+ }
+ strncpy(full_path + dfsplen, CIFS_SB(direntry->d_sb)->prepath, pplen);
return full_path;
}
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index fcbdbb6..b867606 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -161,52 +161,18 @@ static void cifs_unix_info_to_inode(struct inode *inode,
spin_unlock(&inode->i_lock);
}
-static const unsigned char *cifs_get_search_path(struct cifs_sb_info *cifs_sb,
- const char *search_path)
-{
- int tree_len;
- int path_len;
- int i;
- char *tmp_path;
- struct cifsTconInfo *pTcon = cifs_sb->tcon;
-
- 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);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)
- for (i = 0; i < tree_len; i++) {
- if (tmp_path[i] == '\\')
- tmp_path[i] = '/';
- }
- 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)
+ const unsigned char *full_path, struct super_block *sb, int xid)
{
int rc = 0;
FILE_UNIX_BASIC_INFO findData;
struct cifsTconInfo *pTcon;
struct inode *inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- const unsigned char *full_path;
bool is_dfs_referral = false;
pTcon = cifs_sb->tcon;
- cFYI(1, ("Getting info on %s", search_path));
-
- full_path = cifs_get_search_path(cifs_sb, search_path);
+ cFYI(1, ("Getting info on %s", full_path));
try_again_CIFSSMBUnixQPathInfo:
/* could have done a find first instead but this returns more info */
@@ -218,10 +184,6 @@ try_again_CIFSSMBUnixQPathInfo:
if (rc) {
if (rc == -EREMOTE && !is_dfs_referral) {
is_dfs_referral = true;
- if (full_path != search_path) {
- kfree(full_path);
- full_path = search_path;
- }
goto try_again_CIFSSMBUnixQPathInfo;
}
goto cgiiu_exit;
@@ -271,8 +233,6 @@ try_again_CIFSSMBUnixQPathInfo:
cifs_set_ops(inode, is_dfs_referral);
}
cgiiu_exit:
- if (full_path != search_path)
- kfree(full_path);
return rc;
}
@@ -380,20 +340,19 @@ static int get_sfu_mode(struct inode *inode,
}
int cifs_get_inode_info(struct inode **pinode,
- const unsigned char *search_path, FILE_ALL_INFO *pfindData,
+ const unsigned char *full_path, FILE_ALL_INFO *pfindData,
struct super_block *sb, int xid, const __u16 *pfid)
{
int rc = 0;
struct cifsTconInfo *pTcon;
struct inode *inode;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
- const unsigned char *full_path = NULL;
char *buf = NULL;
bool adjustTZ = false;
bool is_dfs_referral = false;
pTcon = cifs_sb->tcon;
- cFYI(1, ("Getting info on %s", search_path));
+ cFYI(1, ("Getting info on %s", full_path));
if ((pfindData == NULL) && (*pinode != NULL)) {
if (CIFS_I(*pinode)->clientCanCacheRead) {
@@ -409,8 +368,6 @@ int cifs_get_inode_info(struct inode **pinode,
return -ENOMEM;
pfindData = (FILE_ALL_INFO *)buf;
- full_path = cifs_get_search_path(cifs_sb, search_path);
-
try_again_CIFSSMBQPathInfo:
/* could do find first instead but this returns more info */
rc = CIFSSMBQPathInfo(xid, pTcon, full_path, pfindData,
@@ -432,10 +389,6 @@ try_again_CIFSSMBQPathInfo:
if (rc) {
if (rc == -EREMOTE && !is_dfs_referral) {
is_dfs_referral = true;
- if (full_path != search_path) {
- kfree(full_path);
- full_path = search_path;
- }
goto try_again_CIFSSMBQPathInfo;
}
goto cgii_exit;
@@ -470,7 +423,7 @@ try_again_CIFSSMBQPathInfo:
__u64 inode_num;
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
- search_path, &inode_num,
+ full_path, &inode_num,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -539,7 +492,7 @@ try_again_CIFSSMBQPathInfo:
(cifsInfo->cifsAttrs & ATTR_SYSTEM)) {
if (decode_sfu_inode(inode,
le64_to_cpu(pfindData->EndOfFile),
- search_path,
+ full_path,
cifs_sb, xid))
cFYI(1, ("Unrecognized sfu inode type"));
@@ -582,12 +535,12 @@ try_again_CIFSSMBQPathInfo:
/* fill in 0777 bits from ACL */
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
cFYI(1, ("Getting mode bits from ACL"));
- acl_to_uid_mode(inode, search_path, pfid);
+ acl_to_uid_mode(inode, full_path, pfid);
}
#endif
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
/* fill in remaining high mode bits e.g. SUID, VTX */
- get_sfu_mode(inode, search_path, cifs_sb, xid);
+ get_sfu_mode(inode, full_path, cifs_sb, xid);
} else if (atomic_read(&cifsInfo->inUse) == 0) {
inode->i_uid = cifs_sb->mnt_uid;
inode->i_gid = cifs_sb->mnt_gid;
@@ -599,8 +552,6 @@ try_again_CIFSSMBQPathInfo:
cifs_set_ops(inode, is_dfs_referral);
}
cgii_exit:
- if (full_path != search_path)
- kfree(full_path);
kfree(buf);
return rc;
}
next reply other threads:[~2008-05-13 22:45 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-05-13 22:45 Steve French [this message]
2008-05-14 11:50 ` dfs path construction fix - send dfs paths on all path based operations on share in dfs Igor Mammedov
[not found] ` <524f69650805141150u3975b19al9b33f76378b28be3@mail.gmail.com>
[not found] ` <524f69650805141853t2ca20b25hd8fa79d698445a62@mail.gmail.com>
2008-05-15 6:22 ` Steve French
2008-05-16 10:03 ` Igor Mammedov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=524f69650805131545id9be81et97549c74ecd0e7c8@mail.gmail.com \
--to=smfrench@gmail.com \
--cc=jlayton@redhat.com \
--cc=jra@samba.org \
--cc=linux-cifs-client@lists.sa \
--cc=niallain@gmail.com \
--cc=qwerty0987654321@mail.ru \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).