fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / fs / cifs / dir.c
index 749d6fb..66b825a 100644 (file)
@@ -46,7 +46,8 @@ char *
 build_path_from_dentry(struct dentry *direntry)
 {
        struct dentry *temp;
-       int namelen = 0;
+       int namelen;
+       int pplen;
        char *full_path;
        char dirsep;
 
@@ -56,7 +57,9 @@ build_path_from_dentry(struct dentry *direntry)
                when the server crashed */
 
        dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
+       pplen = CIFS_SB(direntry->d_sb)->prepathlen;
 cifs_bp_rename_retry:
+       namelen = pplen; 
        for (temp = direntry; !IS_ROOT(temp);) {
                namelen += (1 + temp->d_name.len);
                temp = temp->d_parent;
@@ -70,7 +73,6 @@ cifs_bp_rename_retry:
        if(full_path == NULL)
                return full_path;
        full_path[namelen] = 0; /* trailing null */
-
        for (temp = direntry; !IS_ROOT(temp);) {
                namelen -= 1 + temp->d_name.len;
                if (namelen < 0) {
@@ -79,7 +81,7 @@ cifs_bp_rename_retry:
                        full_path[namelen] = dirsep;
                        strncpy(full_path + namelen + 1, temp->d_name.name,
                                temp->d_name.len);
-                       cFYI(0, (" name: %s ", full_path + namelen));
+                       cFYI(0, ("name: %s", full_path + namelen));
                }
                temp = temp->d_parent;
                if(temp == NULL) {
@@ -88,18 +90,23 @@ cifs_bp_rename_retry:
                        return NULL;
                }
        }
-       if (namelen != 0) {
+       if (namelen != pplen) {
                cERROR(1,
-                      ("We did not end path lookup where we expected namelen is %d",
+                      ("did not end path lookup where expected namelen is %d",
                        namelen));
-               /* presumably this is only possible if we were racing with a rename 
+               /* presumably this is only possible if racing with a rename 
                of one of the parent directories  (we can not lock the dentries
                above us to prevent this, but retrying should be harmless) */
                kfree(full_path);
-               namelen = 0;
                goto cifs_bp_rename_retry;
        }
-
+       /* DIR_SEP already set for byte  0 / vs \ but not for
+          subsequent slashes in prepath which currently must
+          be entered the right way - not sure if there is an alternative
+          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);
        return full_path;
 }
 
@@ -113,7 +120,7 @@ cifs_bp_rename_retry:
        full_path[namelen+2] = 0;
 BB remove above eight lines BB */
 
-/* Inode operations in similar order to how they appear in the Linux file fs.h */
+/* Inode operations in similar order to how they appear in Linux file fs.h */
 
 int
 cifs_create(struct inode *inode, struct dentry *direntry, int mode,
@@ -139,9 +146,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
        cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
 
-       down(&direntry->d_sb->s_vfs_rename_sem);
        full_path = build_path_from_dentry(direntry);
-       up(&direntry->d_sb->s_vfs_rename_sem);
        if(full_path == NULL) {
                FreeXid(xid);
                return -ENOMEM;
@@ -180,11 +185,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                FreeXid(xid);
                return -ENOMEM;
        }
-
-       rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
+       if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) 
+               rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
                         desiredAccess, CREATE_NOT_DIR,
                         &fileHandle, &oplock, buf, cifs_sb->local_nls,
                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+       else
+               rc = -EIO; /* no NT SMB support fall into legacy open below */
+
        if(rc == -EIO) {
                /* old server, retry the open legacy style */
                rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
@@ -193,7 +201,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        } 
        if (rc) {
-               cFYI(1, ("cifs_create returned 0x%x ", rc));
+               cFYI(1, ("cifs_create returned 0x%x", rc));
        } else {
                /* If Open reported that we actually created a file
                then we now have to set the mode if possible */
@@ -256,18 +264,20 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
                        CIFSSMBClose(xid, pTcon, fileHandle);
                } else if(newinode) {
                        pCifsFile =
-                          kmalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
+                          kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
                        
                        if(pCifsFile == NULL)
                                goto cifs_create_out;
-                       memset((char *)pCifsFile, 0,
-                              sizeof (struct cifsFileInfo));
                        pCifsFile->netfid = fileHandle;
                        pCifsFile->pid = current->tgid;
                        pCifsFile->pInode = newinode;
                        pCifsFile->invalidHandle = FALSE;
                        pCifsFile->closePend     = FALSE;
                        init_MUTEX(&pCifsFile->fh_sem);
+                       init_MUTEX(&pCifsFile->lock_sem);
+                       INIT_LIST_HEAD(&pCifsFile->llist);
+                       atomic_set(&pCifsFile->wrtPending,0);
+
                        /* set the following in open now 
                                pCifsFile->pfile = file; */
                        write_lock(&GlobalSMBSeslock);
@@ -318,9 +328,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
        cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
 
-       down(&direntry->d_sb->s_vfs_rename_sem);
        full_path = build_path_from_dentry(direntry);
-       up(&direntry->d_sb->s_vfs_rename_sem);
        if(full_path == NULL)
                rc = -ENOMEM;
        else if (pTcon->ses->capabilities & CAP_UNIX) {
@@ -375,6 +383,10 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
                                         cifs_sb->mnt_cifs_flags & 
                                            CIFS_MOUNT_MAP_SPECIAL_CHR);
 
+                       /* BB FIXME - add handling for backlevel servers
+                          which need legacy open and check for all
+                          calls to SMBOpen for fallback to 
+                          SMBLeagcyOpen */
                        if(!rc) {
                                /* BB Do not bother to decode buf since no
                                   local inode yet to put timestamps in,