]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/cifs/inode.c
Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6
[linux.git] / fs / cifs / inode.c
index a22d667f1069e5eb8485d121f241725de732b8a9..a174605f6afa56cb73a99335cc966f745a9ded6b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/stat.h>
 #include <linux/slab.h>
 #include <linux/pagemap.h>
+#include <linux/freezer.h>
 #include <asm/div64.h>
 #include "cifsfs.h"
 #include "cifspdu.h"
@@ -117,7 +118,7 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
 
        cifs_dbg(FYI, "%s: invalidating inode %llu mapping\n",
                 __func__, cifs_i->uniqueid);
-       cifs_i->invalid_mapping = true;
+       set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags);
 }
 
 /*
@@ -177,7 +178,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
        else
                cifs_i->time = jiffies;
 
-       cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
+       if (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)
+               set_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
+       else
+               clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags);
 
        cifs_i->server_eof = fattr->cf_eof;
        /*
@@ -1121,7 +1125,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
        }
 
        /* try to set DELETE_ON_CLOSE */
-       if (!cifsInode->delete_pending) {
+       if (!test_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags)) {
                rc = CIFSSMBSetFileDisposition(xid, tcon, true, fid.netfid,
                                               current->tgid);
                /*
@@ -1138,7 +1142,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
                        rc = -EBUSY;
                        goto undo_rename;
                }
-               cifsInode->delete_pending = true;
+               set_bit(CIFS_INO_DELETE_PENDING, &cifsInode->flags);
        }
 
 out_close:
@@ -1759,23 +1763,62 @@ int
 cifs_invalidate_mapping(struct inode *inode)
 {
        int rc = 0;
-       struct cifsInodeInfo *cifs_i = CIFS_I(inode);
-
-       cifs_i->invalid_mapping = false;
 
        if (inode->i_mapping && inode->i_mapping->nrpages != 0) {
                rc = invalidate_inode_pages2(inode->i_mapping);
-               if (rc) {
+               if (rc)
                        cifs_dbg(VFS, "%s: could not invalidate inode %p\n",
                                 __func__, inode);
-                       cifs_i->invalid_mapping = true;
-               }
        }
 
        cifs_fscache_reset_inode_cookie(inode);
        return rc;
 }
 
+/**
+ * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks
+ * @word: long word containing the bit lock
+ */
+static int
+cifs_wait_bit_killable(void *word)
+{
+       if (fatal_signal_pending(current))
+               return -ERESTARTSYS;
+       freezable_schedule_unsafe();
+       return 0;
+}
+
+int
+cifs_revalidate_mapping(struct inode *inode)
+{
+       int rc;
+       unsigned long *flags = &CIFS_I(inode)->flags;
+
+       rc = wait_on_bit_lock(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
+                               TASK_KILLABLE);
+       if (rc)
+               return rc;
+
+       if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) {
+               rc = cifs_invalidate_mapping(inode);
+               if (rc)
+                       set_bit(CIFS_INO_INVALID_MAPPING, flags);
+       }
+
+       clear_bit_unlock(CIFS_INO_LOCK, flags);
+       smp_mb__after_atomic();
+       wake_up_bit(flags, CIFS_INO_LOCK);
+
+       return rc;
+}
+
+int
+cifs_zap_mapping(struct inode *inode)
+{
+       set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags);
+       return cifs_revalidate_mapping(inode);
+}
+
 int cifs_revalidate_file_attr(struct file *filp)
 {
        int rc = 0;
@@ -1842,9 +1885,7 @@ int cifs_revalidate_file(struct file *filp)
        if (rc)
                return rc;
 
-       if (CIFS_I(inode)->invalid_mapping)
-               rc = cifs_invalidate_mapping(inode);
-       return rc;
+       return cifs_revalidate_mapping(inode);
 }
 
 /* revalidate a dentry's inode attributes */
@@ -1857,9 +1898,7 @@ int cifs_revalidate_dentry(struct dentry *dentry)
        if (rc)
                return rc;
 
-       if (CIFS_I(inode)->invalid_mapping)
-               rc = cifs_invalidate_mapping(inode);
-       return rc;
+       return cifs_revalidate_mapping(inode);
 }
 
 int cifs_getattr(struct vfsmount *mnt, struct dentry *dentry,