[linux-cifs-client] [PATCH 4/6] [CIFS] change
cifs_setup_session to take a unc string arg
Jeff Layton
jlayton at redhat.com
Wed Nov 7 14:58:05 GMT 2007
On Wed, 7 Nov 2007 08:10:22 -0600
"Steve French" <smfrench at gmail.com> wrote:
> Reconnection of tcp session after network failure today assumes that
> the IP address stays the same (we reconnect to the same ip address)
> but eventually we should be able to handle the case in which the host
> has gone down but been mapped to a different ip address. This also
> seems to require saving the host name in the TCP_Server_Info struct.
>
Sounds reasonable. If we're going to do that though, maybe it makes
sense to do this parsing from cifs_mount (during the phase where
we parse arguments) instead of doing it from the session setup.
> On Nov 7, 2007 5:31 AM, Q (Igor Mammedov) <qwerty0987654321 at mail.ru>
> wrote:
> > Wouldn't it be better if we saved hostname portion of unc in some
> > field of TCP_Server_Info struct? That would result in more
> > reusability of it in future and we wouldn't have to change
> > signatures whenever we wish to use it.
> >
> > Jeff Layton wrote:
> > > ...then extract the host portion of the UNC string so that we can
> >
> > > use in SPNEGO.
> > >
> > > Signed-off-by: Jeff Layton <jlayton at redhat.com>
> > > ---
> > > fs/cifs/cifsproto.h | 2 +-
> > > fs/cifs/cifssmb.c | 6 ++++--
> > > fs/cifs/connect.c | 46
> > > ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed,
> > > 49 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
> > > index dd1d7c2..b256e8a 100644
> > > --- a/fs/cifs/cifsproto.h
> > > +++ b/fs/cifs/cifsproto.h
> > > @@ -107,7 +107,7 @@ void cifs_proc_init(void);
> > > void cifs_proc_clean(void);
> > >
> > > extern int cifs_setup_session(unsigned int xid, struct
> > > cifsSesInfo *pSesInfo,
> > > - struct nls_table *nls_info);
> > > + struct nls_table *nls_info, const char
> > > *unc); extern int CIFSSMBNegotiate(unsigned int xid, struct
> > > cifsSesInfo *ses);
> > >
> > > extern int CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
> > > diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> > > index 0bb3e43..49ad995 100644
> > > --- a/fs/cifs/cifssmb.c
> > > +++ b/fs/cifs/cifssmb.c
> > > @@ -157,7 +157,8 @@ small_smb_init(int smb_command, int wct,
> > > struct cifsTconInfo *tcon, down(&tcon->ses->sesSem);
> > > if (tcon->ses->status == CifsNeedReconnect)
> > > rc = cifs_setup_session(0,
> > > tcon->ses,
> > > -
> > > nls_codepage);
> > > +
> > > nls_codepage,
> > > +
> > > tcon->treeName); if (!rc && (tcon->tidStatus ==
> > > CifsNeedReconnect)) { mark_open_files_invalid(tcon);
> > > rc = CIFSTCon(0, tcon->ses,
> > > tcon->treeName, @@ -302,7 +303,8 @@ smb_init(int smb_command, int
> > > wct, struct cifsTconInfo *tcon, down(&tcon->ses->sesSem);
> > > if (tcon->ses->status == CifsNeedReconnect)
> > > rc = cifs_setup_session(0,
> > > tcon->ses,
> > > -
> > > nls_codepage);
> > > +
> > > nls_codepage,
> > > +
> > > tcon->treeName); if (!rc && (tcon->tidStatus ==
> > > CifsNeedReconnect)) { mark_open_files_invalid(tcon);
> > > rc = CIFSTCon(0, tcon->ses,
> > > tcon->treeName, diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> > > index 380ee99..14b564e 100644
> > > --- a/fs/cifs/connect.c
> > > +++ b/fs/cifs/connect.c
> > > @@ -1996,7 +1996,8 @@ cifs_mount(struct super_block *sb, struct
> > > cifs_sb_info *cifs_sb, down(&pSesInfo->sesSem);
> > > /* BB FIXME need to pass vol->secFlgs BB */
> > > rc = cifs_setup_session(xid, pSesInfo,
> > > - cifs_sb->local_nls);
> > > + cifs_sb->local_nls,
> > > + volume_info.UNC);
> > > up(&pSesInfo->sesSem);
> > > if (!rc)
> > > atomic_inc(&srvTcp->socketUseCount);
> > > @@ -3508,13 +3509,51 @@ cifs_umount(struct super_block *sb,
> > > struct cifs_sb_info *cifs_sb) return rc; /* BB check if we
> > > should always return zero here */ }
> > >
> > > +/* extract the host portion of the UNC string */
> > > +static char *
> > > +extract_hostname_from_unc(const char *unc)
> > > +{
> > > + const char *src;
> > > + char *dst, *delim;
> > > + unsigned int len;
> > > +
> > > + /* skip double chars at beginning of string */
> > > + /* BB: check validity of these bytes? */
> > > + src = unc + 2;
> > > +
> > > + delim = strchr(src, '/');
> > > + if (!delim) {
> > > + delim = strchr(src, '\\');
> > > + if (!delim)
> > > + return ERR_PTR(-EINVAL);
> > > + }
> > > +
> > > + len = delim - src;
> > > + dst = kmalloc((len + 1), GFP_KERNEL);
> > > + if (dst == NULL)
> > > + return ERR_PTR(-ENOMEM);
> > > +
> > > + memcpy(dst, src, len);
> > > + dst[len] = '\0';
> > > +
> > > + return dst;
> > > +}
> > > +
> > > int cifs_setup_session(unsigned int xid, struct cifsSesInfo
> > > *pSesInfo,
> > > - struct nls_table
> > > *nls_info)
> > > + struct nls_table *nls_info, const char *unc)
> > > {
> > > int rc = 0;
> > > char ntlm_session_key[CIFS_SESS_KEY_SIZE];
> > > int ntlmv2_flag = FALSE;
> > > int first_time = 0;
> > > + char *hostname;
> > > +
> > > + hostname = extract_hostname_from_unc(unc);
> > > + if (IS_ERR(hostname)) {
> > > + rc = PTR_ERR(hostname);
> > > + hostname = NULL;
> > > + goto ss_err_exit;
> > > + }
> > >
> > > /* what if server changes its buffer size after dropping
> > > the session? */ if (pSesInfo->server->maxBuf == 0) /* no need to
> > > send on reconnect */ { @@ -3627,6 +3666,9 @@ int
> > > cifs_setup_session(unsigned int xid, struct cifsSesInfo
> > > *pSesInfo, } }
> > > ss_err_exit:
> > > + if (hostname)
> > > + kfree(hostname);
> > > +
> > > return rc;
> > > }
> > >
> >
> >
> > --
> >
> > Best regards,
> >
> > -------------------------
> > Igor Mammedov,
> > niallain "at" gmail.com
> >
> >
> >
> >
> >
>
>
>
> --
> Thanks,
>
> Steve
--
Jeff Layton <jlayton at redhat.com>
More information about the linux-cifs-client
mailing list