patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / cifs / link.c
index 8deba26..f257ff0 100644 (file)
@@ -44,10 +44,18 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
        cifs_sb_target = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb_target->tcon;
 
-/* No need to check for cross device links since server will do that - BB note DFS case in future though (when we may have to check) */
+/* No need to check for cross device links since server will do that
+   BB note DFS case in future though (when we may have to check) */
 
+       down(&inode->i_sb->s_vfs_rename_sem);
        fromName = build_path_from_dentry(old_file);
        toName = build_path_from_dentry(direntry);
+       up(&inode->i_sb->s_vfs_rename_sem);
+       if((fromName == NULL) || (toName == NULL)) {
+               rc = -ENOMEM;
+               goto cifs_hl_exit;
+       }
+
        if (cifs_sb_target->tcon->ses->capabilities & CAP_UNIX)
                rc = CIFSUnixCreateHardLink(xid, pTcon, fromName, toName,
                                            cifs_sb_target->local_nls);
@@ -70,6 +78,7 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
        cifsInode = CIFS_I(old_file->d_inode);
        cifsInode->time = 0;    /* will force revalidate to go get info when needed */
 
+cifs_hl_exit:
        if (fromName)
                kfree(fromName);
        if (toName)
@@ -90,7 +99,15 @@ cifs_follow_link(struct dentry *direntry, struct nameidata *nd)
        struct cifsTconInfo *pTcon;
 
        xid = GetXid();
+
+       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;
+       }
        cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
        cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
@@ -149,7 +166,15 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
        cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
 
+       down(&inode->i_sb->s_vfs_rename_sem);
        full_path = build_path_from_dentry(direntry);
+       up(&inode->i_sb->s_vfs_rename_sem);
+
+       if(full_path == NULL) {
+               FreeXid(xid);
+               return -ENOMEM;
+       }
+
        cFYI(1, ("Full path: %s ", full_path));
        cFYI(1, ("symname is %s", symname));
 
@@ -185,7 +210,7 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname)
 }
 
 int
-cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
+cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
 {
        struct inode *inode = direntry->d_inode;
        int rc = -EACCES;
@@ -204,7 +229,18 @@ cifs_readlink(struct dentry *direntry, char *pBuffer, int buflen)
        xid = GetXid();
        cifs_sb = CIFS_SB(inode->i_sb);
        pTcon = cifs_sb->tcon;
+
+/* BB would it be safe against deadlock to grab this sem 
+      even though rename itself grabs the sem and calls lookup? */
+/*       down(&inode->i_sb->s_vfs_rename_sem);*/
        full_path = build_path_from_dentry(direntry);
+/*       up(&inode->i_sb->s_vfs_rename_sem);*/
+
+       if(full_path == NULL) {
+               FreeXid(xid);
+               return -ENOMEM;
+       }
+
        cFYI(1,
             ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
              full_path, inode, pBuffer, buflen));