Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / fs / cifs / inode.c
index 29b9ea2..62b324f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   fs/cifs/inode.c
  *
- *   Copyright (C) International Business Machines  Corp., 2002,2008
+ *   Copyright (C) International Business Machines  Corp., 2002,2010
  *   Author(s): Steve French (sfrench@us.ibm.com)
  *
  *   This library is free software; you can redistribute it and/or modify
@@ -86,30 +86,30 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
 {
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
 
-       cFYI(1, ("%s: revalidating inode %llu", __func__, cifs_i->uniqueid));
+       cFYI(1, "%s: revalidating inode %llu", __func__, cifs_i->uniqueid);
 
        if (inode->i_state & I_NEW) {
-               cFYI(1, ("%s: inode %llu is new", __func__, cifs_i->uniqueid));
+               cFYI(1, "%s: inode %llu is new", __func__, cifs_i->uniqueid);
                return;
        }
 
        /* don't bother with revalidation if we have an oplock */
        if (cifs_i->clientCanCacheRead) {
-               cFYI(1, ("%s: inode %llu is oplocked", __func__,
-                        cifs_i->uniqueid));
+               cFYI(1, "%s: inode %llu is oplocked", __func__,
+                        cifs_i->uniqueid);
                return;
        }
 
         /* revalidate if mtime or size have changed */
        if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
            cifs_i->server_eof == fattr->cf_eof) {
-               cFYI(1, ("%s: inode %llu is unchanged", __func__,
-                        cifs_i->uniqueid));
+               cFYI(1, "%s: inode %llu is unchanged", __func__,
+                        cifs_i->uniqueid);
                return;
        }
 
-       cFYI(1, ("%s: invalidating inode %llu mapping", __func__,
-                cifs_i->uniqueid));
+       cFYI(1, "%s: invalidating inode %llu mapping", __func__,
+                cifs_i->uniqueid);
        cifs_i->invalid_mapping = true;
 }
 
@@ -137,15 +137,14 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
                inode->i_mode = fattr->cf_mode;
 
        cifs_i->cifsAttrs = fattr->cf_cifsattrs;
-       cifs_i->uniqueid = fattr->cf_uniqueid;
 
        if (fattr->cf_flags & CIFS_FATTR_NEED_REVAL)
                cifs_i->time = 0;
        else
                cifs_i->time = jiffies;
 
-       cFYI(1, ("inode 0x%p old_time=%ld new_time=%ld", inode,
-                oldtime, cifs_i->time));
+       cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode,
+                oldtime, cifs_i->time);
 
        cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
 
@@ -170,6 +169,17 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
        cifs_set_ops(inode, fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL);
 }
 
+void
+cifs_fill_uniqueid(struct super_block *sb, struct cifs_fattr *fattr)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+               return;
+
+       fattr->cf_uniqueid = iunique(sb, ROOT_I);
+}
+
 /* Fill a cifs_fattr struct with info from FILE_UNIX_BASIC_INFO. */
 void
 cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
@@ -227,7 +237,7 @@ cifs_unix_basic_to_fattr(struct cifs_fattr *fattr, FILE_UNIX_BASIC_INFO *info,
                /* safest to call it a file if we do not know */
                fattr->cf_mode |= S_IFREG;
                fattr->cf_dtype = DT_REG;
-               cFYI(1, ("unknown type %d", le32_to_cpu(info->Type)));
+               cFYI(1, "unknown type %d", le32_to_cpu(info->Type));
                break;
        }
 
@@ -256,7 +266,7 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
 {
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
-       cFYI(1, ("creating fake fattr for DFS referral"));
+       cFYI(1, "creating fake fattr for DFS referral");
 
        memset(fattr, 0, sizeof(*fattr));
        fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
@@ -305,7 +315,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
        struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
 
        tcon = cifs_sb->tcon;
-       cFYI(1, ("Getting info on %s", full_path));
+       cFYI(1, "Getting info on %s", full_path);
 
        /* could have done a find first instead but this returns more info */
        rc = CIFSSMBUnixQPathInfo(xid, tcon, full_path, &find_data,
@@ -323,6 +333,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
 
        if (*pinode == NULL) {
                /* get new inode */
+               cifs_fill_uniqueid(sb, &fattr);
                *pinode = cifs_iget(sb, &fattr);
                if (!*pinode)
                        rc = -ENOMEM;
@@ -373,7 +384,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
                                 &bytes_read, &pbuf, &buf_type);
                if ((rc == 0) && (bytes_read >= 8)) {
                        if (memcmp("IntxBLK", pbuf, 8) == 0) {
-                               cFYI(1, ("Block device"));
+                               cFYI(1, "Block device");
                                fattr->cf_mode |= S_IFBLK;
                                fattr->cf_dtype = DT_BLK;
                                if (bytes_read == 24) {
@@ -385,7 +396,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
                                        fattr->cf_rdev = MKDEV(mjr, mnr);
                                }
                        } else if (memcmp("IntxCHR", pbuf, 8) == 0) {
-                               cFYI(1, ("Char device"));
+                               cFYI(1, "Char device");
                                fattr->cf_mode |= S_IFCHR;
                                fattr->cf_dtype = DT_CHR;
                                if (bytes_read == 24) {
@@ -397,7 +408,7 @@ cifs_sfu_type(struct cifs_fattr *fattr, const unsigned char *path,
                                        fattr->cf_rdev = MKDEV(mjr, mnr);
                                }
                        } else if (memcmp("IntxLNK", pbuf, 7) == 0) {
-                               cFYI(1, ("Symlink"));
+                               cFYI(1, "Symlink");
                                fattr->cf_mode |= S_IFLNK;
                                fattr->cf_dtype = DT_LNK;
                        } else {
@@ -439,10 +450,10 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
        else if (rc > 3) {
                mode = le32_to_cpu(*((__le32 *)ea_value));
                fattr->cf_mode &= ~SFBITS_MASK;
-               cFYI(1, ("special bits 0%o org mode 0%o", mode,
-                        fattr->cf_mode));
+               cFYI(1, "special bits 0%o org mode 0%o", mode,
+                        fattr->cf_mode);
                fattr->cf_mode = (mode & SFBITS_MASK) | fattr->cf_mode;
-               cFYI(1, ("special mode bits 0%o", mode));
+               cFYI(1, "special mode bits 0%o", mode);
        }
 
        return 0;
@@ -548,11 +559,11 @@ int cifs_get_inode_info(struct inode **pinode,
        struct cifs_fattr fattr;
 
        pTcon = cifs_sb->tcon;
-       cFYI(1, ("Getting info on %s", full_path));
+       cFYI(1, "Getting info on %s", full_path);
 
        if ((pfindData == NULL) && (*pinode != NULL)) {
                if (CIFS_I(*pinode)->clientCanCacheRead) {
-                       cFYI(1, ("No need to revalidate cached inode sizes"));
+                       cFYI(1, "No need to revalidate cached inode sizes");
                        return rc;
                }
        }
@@ -618,7 +629,7 @@ int cifs_get_inode_info(struct inode **pinode,
                                        cifs_sb->mnt_cifs_flags &
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
                        if (rc1 || !fattr.cf_uniqueid) {
-                               cFYI(1, ("GetSrvInodeNum rc %d", rc1));
+                               cFYI(1, "GetSrvInodeNum rc %d", rc1);
                                fattr.cf_uniqueid = iunique(sb, ROOT_I);
                                cifs_autodisable_serverino(cifs_sb);
                        }
@@ -634,13 +645,13 @@ int cifs_get_inode_info(struct inode **pinode,
            cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
                tmprc = cifs_sfu_type(&fattr, full_path, cifs_sb, xid);
                if (tmprc)
-                       cFYI(1, ("cifs_sfu_type failed: %d", tmprc));
+                       cFYI(1, "cifs_sfu_type failed: %d", tmprc);
        }
 
 #ifdef CONFIG_CIFS_EXPERIMENTAL
        /* fill in 0777 bits from ACL */
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
-               cFYI(1, ("Getting mode bits from ACL"));
+               cFYI(1, "Getting mode bits from ACL");
                cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid);
        }
 #endif
@@ -745,7 +756,7 @@ cifs_iget(struct super_block *sb, struct cifs_fattr *fattr)
        struct inode *inode;
 
 retry_iget5_locked:
-       cFYI(1, ("looking for uniqueid=%llu", fattr->cf_uniqueid));
+       cFYI(1, "looking for uniqueid=%llu", fattr->cf_uniqueid);
 
        /* hash down to 32-bits on 32-bit arch */
        hash = cifs_uniqueid_to_ino_t(fattr->cf_uniqueid);
@@ -797,7 +808,7 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino)
                return ERR_PTR(-ENOMEM);
 
        if (rc && cifs_sb->tcon->ipc) {
-               cFYI(1, ("ipc connection - fake read inode"));
+               cFYI(1, "ipc connection - fake read inode");
                inode->i_mode |= S_IFDIR;
                inode->i_nlink = 2;
                inode->i_op = &cifs_ipc_inode_ops;
@@ -859,7 +870,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
         * server times.
         */
        if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
-               cFYI(1, ("CIFS - CTIME changed"));
+               cFYI(1, "CIFS - CTIME changed");
                info_buf.ChangeTime =
                    cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
        } else
@@ -894,8 +905,8 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, int xid,
                        goto out;
        }
 
-       cFYI(1, ("calling SetFileInfo since SetPathInfo for "
-                "times not supported by this server"));
+       cFYI(1, "calling SetFileInfo since SetPathInfo for "
+                "times not supported by this server");
        rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
                         SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
                         CREATE_NOT_DIR, &netfid, &oplock,
@@ -1053,7 +1064,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
        struct iattr *attrs = NULL;
        __u32 dosattr = 0, origattr = 0;
 
-       cFYI(1, ("cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry));
+       cFYI(1, "cifs_unlink, dir=0x%p, dentry=0x%p", dir, dentry);
 
        xid = GetXid();
 
@@ -1072,7 +1083,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
                rc = CIFSPOSIXDelFile(xid, tcon, full_path,
                        SMB_POSIX_UNLINK_FILE_TARGET, cifs_sb->local_nls,
                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
-               cFYI(1, ("posix del rc %d", rc));
+               cFYI(1, "posix del rc %d", rc);
                if ((rc == 0) || (rc == -ENOENT))
                        goto psx_del_no_retry;
        }
@@ -1146,7 +1157,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
        struct inode *newinode = NULL;
        struct cifs_fattr fattr;
 
-       cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
+       cFYI(1, "In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode);
 
        xid = GetXid();
 
@@ -1181,7 +1192,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                        kfree(pInfo);
                        goto mkdir_retry_old;
                } else if (rc) {
-                       cFYI(1, ("posix mkdir returned 0x%x", rc));
+                       cFYI(1, "posix mkdir returned 0x%x", rc);
                        d_drop(direntry);
                } else {
                        if (pInfo->Type == cpu_to_le32(-1)) {
@@ -1198,6 +1209,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                                direntry->d_op = &cifs_dentry_ops;
 
                        cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb);
+                       cifs_fill_uniqueid(inode->i_sb, &fattr);
                        newinode = cifs_iget(inode->i_sb, &fattr);
                        if (!newinode) {
                                kfree(pInfo);
@@ -1207,12 +1219,12 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                        d_instantiate(direntry, newinode);
 
 #ifdef CONFIG_CIFS_DEBUG2
-                       cFYI(1, ("instantiated dentry %p %s to inode %p",
-                               direntry, direntry->d_name.name, newinode));
+                       cFYI(1, "instantiated dentry %p %s to inode %p",
+                               direntry, direntry->d_name.name, newinode);
 
                        if (newinode->i_nlink != 2)
-                               cFYI(1, ("unexpected number of links %d",
-                                       newinode->i_nlink));
+                               cFYI(1, "unexpected number of links %d",
+                                       newinode->i_nlink);
 #endif
                }
                kfree(pInfo);
@@ -1223,7 +1235,7 @@ mkdir_retry_old:
        rc = CIFSSMBMkDir(xid, pTcon, full_path, cifs_sb->local_nls,
                          cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        if (rc) {
-               cFYI(1, ("cifs_mkdir returned 0x%x", rc));
+               cFYI(1, "cifs_mkdir returned 0x%x", rc);
                d_drop(direntry);
        } else {
 mkdir_get_info:
@@ -1326,7 +1338,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
        char *full_path = NULL;
        struct cifsInodeInfo *cifsInode;
 
-       cFYI(1, ("cifs_rmdir, inode = 0x%p", inode));
+       cFYI(1, "cifs_rmdir, inode = 0x%p", inode);
 
        xid = GetXid();
 
@@ -1528,6 +1540,11 @@ cifs_inode_needs_reval(struct inode *inode)
        if (time_after_eq(jiffies, cifs_i->time + HZ))
                return true;
 
+       /* hardlinked files w/ noserverino get "special" treatment */
+       if (!(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) &&
+           S_ISREG(inode->i_mode) && inode->i_nlink != 1)
+               return true;
+
        return false;
 }
 
@@ -1594,9 +1611,9 @@ int cifs_revalidate_dentry(struct dentry *dentry)
                goto check_inval;
        }
 
-       cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
+       cFYI(1, "Revalidate: %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));
+                dentry, dentry->d_time, jiffies);
 
        if (CIFS_SB(sb)->tcon->unix_ext)
                rc = cifs_get_inode_info_unix(&inode, full_path, sb, xid);
@@ -1690,12 +1707,12 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
                rc = CIFSSMBSetFileSize(xid, pTcon, attrs->ia_size, nfid,
                                        npid, false);
                cifsFileInfo_put(open_file);
-               cFYI(1, ("SetFSize for attrs rc = %d", rc));
+               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);
-                       cFYI(1, ("Wrt seteof rc %d", rc));
+                       cFYI(1, "Wrt seteof rc %d", rc);
                }
        } else
                rc = -EINVAL;
@@ -1709,7 +1726,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
                                   false, cifs_sb->local_nls,
                                   cifs_sb->mnt_cifs_flags &
                                        CIFS_MOUNT_MAP_SPECIAL_CHR);
-               cFYI(1, ("SetEOF by path (setattrs) rc = %d", rc));
+               cFYI(1, "SetEOF by path (setattrs) rc = %d", rc);
                if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
                        __u16 netfid;
                        int oplock = 0;
@@ -1726,7 +1743,7 @@ cifs_set_file_size(struct inode *inode, struct iattr *attrs,
                                                  attrs->ia_size,
                                                  &bytes_written, NULL,
                                                  NULL, 1);
-                               cFYI(1, ("wrt seteof rc %d", rc));
+                               cFYI(1, "wrt seteof rc %d", rc);
                                CIFSSMBClose(xid, pTcon, netfid);
                        }
                }
@@ -1754,8 +1771,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
        struct cifs_unix_set_info_args *args = NULL;
        struct cifsFileInfo *open_file;
 
-       cFYI(1, ("setattr_unix on file %s attrs->ia_valid=0x%x",
-                direntry->d_name.name, attrs->ia_valid));
+       cFYI(1, "setattr_unix on file %s attrs->ia_valid=0x%x",
+                direntry->d_name.name, attrs->ia_valid);
 
        xid = GetXid();
 
@@ -1885,8 +1902,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 
        xid = GetXid();
 
-       cFYI(1, ("setattr on file %s attrs->iavalid 0x%x",
-                direntry->d_name.name, attrs->ia_valid));
+       cFYI(1, "setattr on file %s attrs->iavalid 0x%x",
+                direntry->d_name.name, attrs->ia_valid);
 
        if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
                /* check if we have permission to change attrs */
@@ -1943,7 +1960,7 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
                attrs->ia_valid &= ~ATTR_MODE;
 
        if (attrs->ia_valid & ATTR_MODE) {
-               cFYI(1, ("Mode changed to 0%o", attrs->ia_mode));
+               cFYI(1, "Mode changed to 0%o", attrs->ia_mode);
                mode = attrs->ia_mode;
        }
 
@@ -2029,7 +2046,7 @@ cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 #if 0
 void cifs_delete_inode(struct inode *inode)
 {
-       cFYI(1, ("In cifs_delete_inode, inode = 0x%p", inode));
+       cFYI(1, "In cifs_delete_inode, inode = 0x%p", inode);
        /* may have to add back in if and when safe distributed caching of
           directories added e.g. via FindNotify */
 }