]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/cifs/inode.c
[CIFS] Remove redundant test
[linux-2.6-omap-h63xx.git] / fs / cifs / inode.c
index 8ac4eabc1f8bb8d73d1711697e6e8fed2bd97fe3..b8821b0e73de510a3ad168a38eac5b1dcf5e8927 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/inode.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2007
+ *   Copyright (C) International Business Machines  Corp., 2002,2008
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -621,6 +621,47 @@ static const struct inode_operations cifs_ipc_inode_ops = {
        .lookup = cifs_lookup,
 };
 
+static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
+{
+       int pplen = cifs_sb->prepathlen;
+       int dfsplen;
+       char *full_path = NULL;
+
+       /* if no prefix path, simply set path to the root of share to "" */
+       if (pplen == 0) {
+               full_path = kmalloc(1, GFP_KERNEL);
+               if (full_path)
+                       full_path[0] = 0;
+               return full_path;
+       }
+
+       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;
+
+       full_path = kmalloc(dfsplen + pplen + 1, GFP_KERNEL);
+       if (full_path == NULL)
+               return full_path;
+
+       if (dfsplen) {
+               strncpy(full_path, cifs_sb->tcon->treeName, dfsplen);
+               /* switch slash direction in prepath depending on whether
+                * windows or posix style path names
+                */
+               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->prepath, pplen);
+       full_path[dfsplen + pplen] = 0; /* add trailing null */
+       return full_path;
+}
+
 /* gets root inode */
 struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
 {
@@ -628,6 +669,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
        struct cifs_sb_info *cifs_sb;
        struct inode *inode;
        long rc;
+       char *full_path;
 
        inode = iget_locked(sb, ino);
        if (!inode)
@@ -636,13 +678,17 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
                return inode;
 
        cifs_sb = CIFS_SB(inode->i_sb);
-       xid = GetXid();
+       full_path = build_path_to_root(cifs_sb);
+       if (full_path == NULL)
+               return ERR_PTR(-ENOMEM);
 
+       xid = GetXid();
        if (cifs_sb->tcon->unix_ext)
-               rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
+               rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
+                                               xid);
        else
-               rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid,
-                                        NULL);
+               rc = cifs_get_inode_info(&inode, full_path, NULL, inode->i_sb,
+                                               xid, NULL);
        if (rc && cifs_sb->tcon->ipc) {
                cFYI(1, ("ipc connection - fake read inode"));
                inode->i_mode |= S_IFDIR;
@@ -652,6 +698,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
                inode->i_uid = cifs_sb->mnt_uid;
                inode->i_gid = cifs_sb->mnt_gid;
        } else if (rc) {
+               kfree(full_path);
                _FreeXid(xid);
                iget_failed(inode);
                return ERR_PTR(rc);
@@ -659,6 +706,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
 
        unlock_new_inode(inode);
 
+       kfree(full_path);
        /* can not call macro FreeXid here since in a void func
         * TODO: This is no longer true
         */
@@ -1293,12 +1341,9 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
        struct cifs_sb_info *cifs_sb_source;
        struct cifs_sb_info *cifs_sb_target;
        struct cifsTconInfo *tcon;
-       struct cifsInodeInfo *target_cinode;
        FILE_UNIX_BASIC_INFO *info_buf_source = NULL;
        FILE_UNIX_BASIC_INFO *info_buf_target;
-       __u16 dstfid;
-       int xid, rc, tmprc, oplock = 0;
-       bool delete_already_pending;
+       int xid, rc, tmprc;
 
        cifs_sb_target = CIFS_SB(target_dir->i_sb);
        cifs_sb_source = CIFS_SB(source_dir->i_sb);
@@ -1348,104 +1393,38 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry,
                }
 
                info_buf_target = info_buf_source + 1;
-               rc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
+               tmprc = CIFSSMBUnixQPathInfo(xid, tcon, fromName,
                                        info_buf_source,
                                        cifs_sb_source->local_nls,
                                        cifs_sb_source->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
-               if (rc != 0)
+               if (tmprc != 0)
                        goto unlink_target;
 
-               rc = CIFSSMBUnixQPathInfo(xid, tcon,
+               tmprc = CIFSSMBUnixQPathInfo(xid, tcon,
                                        toName, info_buf_target,
                                        cifs_sb_target->local_nls,
                                        /* remap based on source sb */
                                        cifs_sb_source->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
 
-               if (rc == 0 && (info_buf_source->UniqueId ==
-                               info_buf_target->UniqueId))
+               if (tmprc == 0 && (info_buf_source->UniqueId ==
+                                  info_buf_target->UniqueId)) {
                        /* same file, POSIX says that this is a noop */
+                       rc = 0;
                        goto cifs_rename_exit;
-
-               rc = -EEXIST;
+               }
        } /* else ... BB we could add the same check for Windows by
                     checking the UniqueId via FILE_INTERNAL_INFO */
 
-       if ((rc == -EACCES) || (rc == -EEXIST)) {
 unlink_target:
-               /* don't bother if this is a negative dentry */
-               if (!target_dentry->d_inode)
-                       goto cifs_rename_exit;
-
-               target_cinode = CIFS_I(target_dentry->d_inode);
-
-               /* try to move the target out of the way */
-               tmprc = CIFSSMBOpen(xid, tcon, toName, FILE_OPEN, DELETE,
-                                   CREATE_NOT_DIR, &dstfid, &oplock, NULL,
-                                   cifs_sb_target->local_nls,
-                                   cifs_sb_target->mnt_cifs_flags &
-                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
+       if ((rc == -EACCES) || (rc == -EEXIST)) {
+               tmprc = cifs_unlink(target_dir, target_dentry);
                if (tmprc)
                        goto cifs_rename_exit;
 
-               /* rename the file to random name */
-               tmprc = CIFSSMBRenameOpenFile(xid, tcon, dstfid, NULL,
-                                             cifs_sb_target->local_nls,
-                                             cifs_sb_target->mnt_cifs_flags &
-                                               CIFS_MOUNT_MAP_SPECIAL_CHR);
-
-               if (tmprc)
-                       goto close_target;
-
-               delete_already_pending = target_cinode->delete_pending;
-
-               if (!delete_already_pending) {
-                       /* set delete on close */
-                       tmprc = CIFSSMBSetFileDisposition(xid, tcon,
-                                                         true, dstfid,
-                                                         current->tgid);
-                       /*
-                        * This hack is for broken samba servers, remove this
-                        * once more fixed ones are in the field.
-                        */
-                       if (tmprc == -ENOENT)
-                               delete_already_pending = false;
-                       else if (tmprc)
-                               goto undo_target_rename;
-
-                       target_cinode->delete_pending = true;
-               }
-
-
                rc = cifs_do_rename(xid, source_dentry, fromName,
                                    target_dentry, toName);
-
-               if (rc == 0)
-                       goto close_target;
-
-               /*
-                * after this point, we can't bother with error handling on
-                * the undo's. This is best effort since we can't do anything
-                * about failures here.
-                */
-               if (!delete_already_pending) {
-                       tmprc = CIFSSMBSetFileDisposition(xid, tcon,
-                                                         false, dstfid,
-                                                         current->tgid);
-                       if (tmprc == 0)
-                               target_cinode->delete_pending = false;
-               }
-
-undo_target_rename:
-               /* rename failed: undo target rename */
-               CIFSSMBRenameOpenFile(xid, tcon, dstfid,
-                                     target_dentry->d_name.name,
-                                     cifs_sb_target->local_nls,
-                                     cifs_sb_target->mnt_cifs_flags &
-                                       CIFS_MOUNT_MAP_SPECIAL_CHR);
-close_target:
-               CIFSSMBClose(xid, tcon, dstfid);
        }
 
 cifs_rename_exit: