[CIFS] Migrate from prefixpath logic
[deliverable/linux.git] / fs / cifs / inode.c
index 8852470b4fbb50b55907cbbd2f4d75357a9f0776..53ea6250a51d0863c6189df66252c92662156863 100644 (file)
@@ -735,10 +735,10 @@ static const struct inode_operations cifs_ipc_inode_ops = {
        .lookup = cifs_lookup,
 };
 
-char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
-                               struct cifsTconInfo *tcon)
+char *cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
+                             struct cifsTconInfo *tcon)
 {
-       int pplen = cifs_sb->prepathlen;
+       int pplen = vol->prepath ? strlen(vol->prepath) : 0;
        int dfsplen;
        char *full_path = NULL;
 
@@ -772,7 +772,7 @@ char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb,
                        }
                }
        }
-       strncpy(full_path + dfsplen, cifs_sb->prepath, pplen);
+       strncpy(full_path + dfsplen, vol->prepath, pplen);
        full_path[dfsplen + pplen] = 0; /* add trailing null */
        return full_path;
 }
@@ -878,25 +878,19 @@ retry_iget5_locked:
 }
 
 /* gets root inode */
-struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
+struct inode *cifs_root_iget(struct super_block *sb)
 {
        int xid;
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        struct inode *inode = NULL;
        long rc;
-       char *full_path;
        struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
 
-       full_path = cifs_build_path_to_root(cifs_sb, tcon);
-       if (full_path == NULL)
-               return ERR_PTR(-ENOMEM);
-
        xid = GetXid();
        if (tcon->unix_ext)
-               rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
+               rc = cifs_get_inode_info_unix(&inode, "", sb, xid);
        else
-               rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
-                                               xid, NULL);
+               rc = cifs_get_inode_info(&inode, "", NULL, sb, xid, NULL);
 
        if (!inode) {
                inode = ERR_PTR(rc);
@@ -922,7 +916,6 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
        }
 
 out:
-       kfree(full_path);
        /* can not call macro FreeXid here since in a void func
         * TODO: This is no longer true
         */
@@ -1683,71 +1676,70 @@ cifs_inode_needs_reval(struct inode *inode)
 /*
  * Zap the cache. Called when invalid_mapping flag is set.
  */
-void
+int
 cifs_invalidate_mapping(struct inode *inode)
 {
-       int rc;
+       int rc = 0;
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
 
        cifs_i->invalid_mapping = false;
 
-       /* write back any cached data */
        if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
-               rc = filemap_write_and_wait(inode->i_mapping);
-               mapping_set_error(inode->i_mapping, rc);
+               rc = invalidate_inode_pages2(inode->i_mapping);
+               if (rc) {
+                       cERROR(1, "%s: could not invalidate inode %p", __func__,
+                              inode);
+                       cifs_i->invalid_mapping = true;
+               }
        }
-       invalidate_remote_inode(inode);
+
        cifs_fscache_reset_inode_cookie(inode);
+       return rc;
 }
 
-int cifs_revalidate_file(struct file *filp)
+int cifs_revalidate_file_attr(struct file *filp)
 {
        int rc = 0;
        struct inode *inode = filp->f_path.dentry->d_inode;
        struct cifsFileInfo *cfile = (struct cifsFileInfo *) filp->private_data;
 
        if (!cifs_inode_needs_reval(inode))
-               goto check_inval;
+               return rc;
 
        if (tlink_tcon(cfile->tlink)->unix_ext)
                rc = cifs_get_file_info_unix(filp);
        else
                rc = cifs_get_file_info(filp);
 
-check_inval:
-       if (CIFS_I(inode)->invalid_mapping)
-               cifs_invalidate_mapping(inode);
-
        return rc;
 }
 
-/* revalidate a dentry's inode attributes */
-int cifs_revalidate_dentry(struct dentry *dentry)
+int cifs_revalidate_dentry_attr(struct dentry *dentry)
 {
        int xid;
        int rc = 0;
-       char *full_path = NULL;
        struct inode *inode = dentry->d_inode;
        struct super_block *sb = dentry->d_sb;
+       char *full_path = NULL;
 
        if (inode == NULL)
                return -ENOENT;
 
-       xid = GetXid();
-
        if (!cifs_inode_needs_reval(inode))
-               goto check_inval;
+               return rc;
+
+       xid = GetXid();
 
        /* can not safely grab the rename sem here if rename calls revalidate
           since that would deadlock */
        full_path = build_path_from_dentry(dentry);
        if (full_path == NULL) {
                rc = -ENOMEM;
-               goto check_inval;
+               goto out;
        }
 
-       cFYI(1, "Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
-                "jiffies %ld", full_path, inode, inode->i_count.counter,
+       cFYI(1, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time "
+                "%ld jiffies %ld", full_path, inode, inode->i_count.counter,
                 dentry, dentry->d_time, jiffies);
 
        if (cifs_sb_master_tcon(CIFS_SB(sb))->unix_ext)
@@ -1756,41 +1748,83 @@ int cifs_revalidate_dentry(struct dentry *dentry)
                rc = cifs_get_inode_info(&inode, full_path, NULL, sb,
                                         xid, NULL);
 
-check_inval:
-       if (CIFS_I(inode)->invalid_mapping)
-               cifs_invalidate_mapping(inode);
-
+out:
        kfree(full_path);
        FreeXid(xid);
        return rc;
 }
 
+int cifs_revalidate_file(struct file *filp)
+{
+       int rc;
+       struct inode *inode = filp->f_path.dentry->d_inode;
+
+       rc = cifs_revalidate_file_attr(filp);
+       if (rc)
+               return rc;
+
+       if (CIFS_I(inode)->invalid_mapping)
+               rc = cifs_invalidate_mapping(inode);
+       return rc;
+}
+
+/* revalidate a dentry's inode attributes */
+int cifs_revalidate_dentry(struct dentry *dentry)
+{
+       int rc;
+       struct inode *inode = dentry->d_inode;
+
+       rc = cifs_revalidate_dentry_attr(dentry);
+       if (rc)
+               return rc;
+
+       if (CIFS_I(inode)->invalid_mapping)
+               rc = cifs_invalidate_mapping(inode);
+       return rc;
+}
+
 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,
                 struct kstat *stat)
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
        struct cifsTconInfo *tcon = cifs_sb_master_tcon(cifs_sb);
-       int err = cifs_revalidate_dentry(dentry);
-
-       if (!err) {
-               generic_fillattr(dentry->d_inode, stat);
-               stat->blksize = CIFS_MAX_MSGSIZE;
-               stat->ino = CIFS_I(dentry->d_inode)->uniqueid;
+       struct inode *inode = dentry->d_inode;
+       int rc;
 
-               /*
-                * If on a multiuser mount without unix extensions, and the
-                * admin hasn't overridden them, set the ownership to the
-                * fsuid/fsgid of the current process.
-                */
-               if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
-                   !tcon->unix_ext) {
-                       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
-                               stat->uid = current_fsuid();
-                       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
-                               stat->gid = current_fsgid();
+       /*
+        * We need to be sure that all dirty pages are written and the server
+        * has actual ctime, mtime and file length.
+        */
+       if (!CIFS_I(inode)->clientCanCacheRead && inode->i_mapping &&
+           inode->i_mapping->nrpages != 0) {
+               rc = filemap_fdatawait(inode->i_mapping);
+               if (rc) {
+                       mapping_set_error(inode->i_mapping, rc);
+                       return rc;
                }
        }
-       return err;
+
+       rc = cifs_revalidate_dentry_attr(dentry);
+       if (rc)
+               return rc;
+
+       generic_fillattr(inode, stat);
+       stat->blksize = CIFS_MAX_MSGSIZE;
+       stat->ino = CIFS_I(inode)->uniqueid;
+
+       /*
+        * If on a multiuser mount without unix extensions, and the admin hasn't
+        * overridden them, set the ownership to the fsuid/fsgid of the current
+        * process.
+        */
+       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) &&
+           !tcon->unix_ext) {
+               if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID))
+                       stat->uid = current_fsuid();
+               if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID))
+                       stat->gid = current_fsgid();
+       }
+       return rc;
 }
 
 static int cifs_truncate_page(struct address_space *mapping, loff_t from)
@@ -1832,6 +1866,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink = NULL;
        struct cifsTconInfo *pTcon = NULL;
+       struct cifs_io_parms io_parms;
 
        /*
         * To avoid spurious oplock breaks from server, in the case of
@@ -1853,8 +1888,14 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
                cFYI(1, "SetFSize for attrs rc = %d", rc);
                if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
                        unsigned int bytes_written;
-                       rc = CIFSSMBWrite(xid, pTcon, nfid, 0, attrs->ia_size,
-                                         &bytes_written, NULL, NULL, 1);
+
+                       io_parms.netfid = nfid;
+                       io_parms.pid = npid;
+                       io_parms.tcon = pTcon;
+                       io_parms.offset = 0;
+                       io_parms.length = attrs->ia_size;
+                       rc = CIFSSMBWrite(xid, &io_parms, &bytes_written,
+                                         NULL, NULL, 1);
                        cFYI(1, "Wrt seteof rc %d", rc);
                }
        } else
@@ -1889,10 +1930,15 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
                        if (rc == 0) {
                                unsigned int bytes_written;
-                               rc = CIFSSMBWrite(xid, pTcon, netfid, 0,
-                                                 attrs->ia_size,
-                                                 &bytes_written, NULL,
-                                                 NULL, 1);
+
+                               io_parms.netfid = netfid;
+                               io_parms.pid = current->tgid;
+                               io_parms.tcon = pTcon;
+                               io_parms.offset = 0;
+                               io_parms.length = attrs->ia_size;
+                               rc = CIFSSMBWrite(xid, &io_parms,
+                                                 &bytes_written,
+                                                 NULL, NULL,  1);
                                cFYI(1, "wrt seteof rc %d", rc);
                                CIFSSMBClose(xid, pTcon, netfid);
                        }
This page took 0.027793 seconds and 5 git commands to generate.