]> err.no Git - linux-2.6/blobdiff - fs/cifs/inode.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
[linux-2.6] / fs / cifs / inode.c
index 4f0ee67eb9540e51d2e980637595461827259758..bc673c8c1e6b59eb7fc48464965db0e3e7835365 100644 (file)
@@ -57,9 +57,13 @@ static void cifs_set_ops(struct inode *inode, const bool is_dfs_referral)
                        inode->i_data.a_ops = &cifs_addr_ops;
                break;
        case S_IFDIR:
+#ifdef CONFIG_CIFS_DFS_UPCALL
                if (is_dfs_referral) {
                        inode->i_op = &cifs_dfs_referral_inode_operations;
                } else {
+#else /* NO DFS support, treat as a directory */
+               {
+#endif
                        inode->i_op = &cifs_dir_inode_ops;
                        inode->i_fop = &cifs_dir_ops;
                }
@@ -207,7 +211,10 @@ try_again_CIFSSMBUnixQPathInfo:
        if (rc) {
                if (rc == -EREMOTE && !is_dfs_referral) {
                        is_dfs_referral = true;
-                       full_path = search_path;
+                       if (full_path != search_path) {
+                               kfree(full_path);
+                               full_path = search_path;
+                       }
                        goto try_again_CIFSSMBUnixQPathInfo;
                }
                goto cgiiu_exit;
@@ -367,7 +374,7 @@ static int get_sfu_mode(struct inode *inode,
 
 int cifs_get_inode_info(struct inode **pinode,
        const unsigned char *search_path, FILE_ALL_INFO *pfindData,
-       struct super_block *sb, int xid)
+       struct super_block *sb, int xid, const __u16 *pfid)
 {
        int rc = 0;
        struct cifsTconInfo *pTcon;
@@ -418,7 +425,10 @@ try_again_CIFSSMBQPathInfo:
        if (rc) {
                if (rc == -EREMOTE && !is_dfs_referral) {
                        is_dfs_referral = true;
-                       full_path = search_path;
+                       if (full_path != search_path) {
+                               kfree(full_path);
+                               full_path = search_path;
+                       }
                        goto try_again_CIFSSMBQPathInfo;
                }
                goto cgii_exit;
@@ -565,7 +575,7 @@ try_again_CIFSSMBQPathInfo:
                /* fill in 0777 bits from ACL */
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
                        cFYI(1, ("Getting mode bits from ACL"));
-                       acl_to_uid_mode(inode, search_path);
+                       acl_to_uid_mode(inode, search_path, pfid);
                }
 #endif
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
@@ -612,7 +622,8 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
        if (cifs_sb->tcon->unix_ext)
                rc = cifs_get_inode_info_unix(&inode, "", inode->i_sb, xid);
        else
-               rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid);
+               rc = cifs_get_inode_info(&inode, "", NULL, inode->i_sb, xid,
+                                        NULL);
        if (rc && cifs_sb->tcon->ipc) {
                cFYI(1, ("ipc connection - fake read inode"));
                inode->i_mode |= S_IFDIR;
@@ -945,7 +956,7 @@ mkdir_get_info:
                                                      inode->i_sb, xid);
                else
                        rc = cifs_get_inode_info(&newinode, full_path, NULL,
-                                                inode->i_sb, xid);
+                                                inode->i_sb, xid, NULL);
 
                if (pTcon->nocase)
                        direntry->d_op = &cifs_ci_dentry_ops;
@@ -1227,7 +1238,7 @@ int cifs_revalidate(struct dentry *direntry)
                }
        } else {
                rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
-                                        direntry->d_sb, xid);
+                                        direntry->d_sb, xid, NULL);
                if (rc) {
                        cFYI(1, ("error on getting revalidate info %d", rc));
 /*                     if (rc != -ENOENT)
@@ -1416,11 +1427,10 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
        }
        cifsInode = CIFS_I(direntry->d_inode);
 
-       /* BB check if we need to refresh inode from server now ? BB */
-
-       if (attrs->ia_valid & ATTR_SIZE) {
+       if ((attrs->ia_valid & ATTR_MTIME) || (attrs->ia_valid & ATTR_SIZE)) {
                /*
-                  Flush data before changing file size on server. If the
+                  Flush data before changing file size or changing the last
+                  write time of the file on the server. If the
                   flush returns error, store it to report later and continue.
                   BB: This should be smarter. Why bother flushing pages that
                   will be truncated anyway? Also, should we error out here if
@@ -1431,7 +1441,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                        CIFS_I(direntry->d_inode)->write_behind_rc = rc;
                        rc = 0;
                }
+       }
 
+       if (attrs->ia_valid & ATTR_SIZE) {
                /* To avoid spurious oplock breaks from server, in the case of
                   inodes that we already have open, avoid doing path based
                   setting of file size if we can do it by handle.