3535#include <linux/delay.h>
3636#include <linux/kthread.h>
3737#include <linux/freezer.h>
38+ #include <linux/namei.h>
3839#include <net/ipv6.h>
3940#include "cifsfs.h"
4041#include "cifspdu.h"
@@ -542,14 +543,12 @@ static const struct super_operations cifs_super_ops = {
542543static struct dentry *
543544cifs_get_root (struct smb_vol * vol , struct super_block * sb )
544545{
545- int xid , rc ;
546- struct inode * inode ;
547- struct qstr name ;
548- struct dentry * dparent = NULL , * dchild = NULL , * alias ;
546+ struct dentry * dentry ;
549547 struct cifs_sb_info * cifs_sb = CIFS_SB (sb );
550- unsigned int i , full_len , len ;
551- char * full_path = NULL , * pstart ;
548+ char * full_path = NULL ;
549+ char * s , * p ;
552550 char sep ;
551+ int xid ;
553552
554553 full_path = cifs_build_path_to_root (vol , cifs_sb ,
555554 cifs_sb_master_tcon (cifs_sb ));
@@ -560,73 +559,32 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
560559
561560 xid = GetXid ();
562561 sep = CIFS_DIR_SEP (cifs_sb );
563- dparent = dget (sb -> s_root );
564- full_len = strlen (full_path );
565- full_path [full_len ] = sep ;
566- pstart = full_path + 1 ;
567-
568- for (i = 1 , len = 0 ; i <= full_len ; i ++ ) {
569- if (full_path [i ] != sep || !len ) {
570- len ++ ;
571- continue ;
572- }
573-
574- full_path [i ] = 0 ;
575- cFYI (1 , "get dentry for %s" , pstart );
576-
577- name .name = pstart ;
578- name .len = len ;
579- name .hash = full_name_hash (pstart , len );
580- dchild = d_lookup (dparent , & name );
581- if (dchild == NULL ) {
582- cFYI (1 , "not exists" );
583- dchild = d_alloc (dparent , & name );
584- if (dchild == NULL ) {
585- dput (dparent );
586- dparent = ERR_PTR (- ENOMEM );
587- goto out ;
588- }
589- }
590-
591- cFYI (1 , "get inode" );
592- if (dchild -> d_inode == NULL ) {
593- cFYI (1 , "not exists" );
594- inode = NULL ;
595- if (cifs_sb_master_tcon (CIFS_SB (sb ))-> unix_ext )
596- rc = cifs_get_inode_info_unix (& inode , full_path ,
597- sb , xid );
598- else
599- rc = cifs_get_inode_info (& inode , full_path ,
600- NULL , sb , xid , NULL );
601- if (rc ) {
602- dput (dchild );
603- dput (dparent );
604- dparent = ERR_PTR (rc );
605- goto out ;
606- }
607- alias = d_materialise_unique (dchild , inode );
608- if (alias != NULL ) {
609- dput (dchild );
610- if (IS_ERR (alias )) {
611- dput (dparent );
612- dparent = ERR_PTR (- EINVAL ); /* XXX */
613- goto out ;
614- }
615- dchild = alias ;
616- }
617- }
618- cFYI (1 , "parent %p, child %p" , dparent , dchild );
619-
620- dput (dparent );
621- dparent = dchild ;
622- len = 0 ;
623- pstart = full_path + i + 1 ;
624- full_path [i ] = sep ;
625- }
626- out :
562+ dentry = dget (sb -> s_root );
563+ p = s = full_path ;
564+
565+ do {
566+ struct inode * dir = dentry -> d_inode ;
567+ struct dentry * child ;
568+
569+ /* skip separators */
570+ while (* s == sep )
571+ s ++ ;
572+ if (!* s )
573+ break ;
574+ p = s ++ ;
575+ /* next separator */
576+ while (* s && * s != sep )
577+ s ++ ;
578+
579+ mutex_lock (& dir -> i_mutex );
580+ child = lookup_one_len (p , dentry , s - p );
581+ mutex_unlock (& dir -> i_mutex );
582+ dput (dentry );
583+ dentry = child ;
584+ } while (!IS_ERR (dentry ));
627585 _FreeXid (xid );
628586 kfree (full_path );
629- return dparent ;
587+ return dentry ;
630588}
631589
632590static int cifs_set_super (struct super_block * sb , void * data )
0 commit comments