cifs: Support fscache indexing rewrite
[linux-2.6-microblaze.git] / fs / cifs / file.c
index 9fee3af..59334be 100644 (file)
@@ -376,8 +376,6 @@ static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file)
        struct cifsLockInfo *li, *tmp;
        struct super_block *sb = inode->i_sb;
 
-       cifs_fscache_release_inode_cookie(inode);
-
        /*
         * Delete any outstanding lock records. We'll lose them when the file
         * is closed anyway.
@@ -570,7 +568,7 @@ int cifs_open(struct inode *inode, struct file *file)
                        spin_lock(&CIFS_I(inode)->deferred_lock);
                        cifs_del_deferred_close(cfile);
                        spin_unlock(&CIFS_I(inode)->deferred_lock);
-                       goto out;
+                       goto use_cache;
                } else {
                        _cifsFileInfo_put(cfile, true, false);
                }
@@ -632,8 +630,6 @@ int cifs_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       cifs_fscache_set_inode_cookie(inode, file);
-
        if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) {
                /*
                 * Time to set mode which we can not set earlier due to
@@ -652,6 +648,15 @@ int cifs_open(struct inode *inode, struct file *file)
                                       cfile->pid);
        }
 
+use_cache:
+       fscache_use_cookie(cifs_inode_cookie(file_inode(file)),
+                          file->f_mode & FMODE_WRITE);
+       if (file->f_flags & O_DIRECT &&
+           (!((file->f_flags & O_ACCMODE) != O_RDONLY) ||
+            file->f_flags & O_APPEND))
+               cifs_invalidate_cache(file_inode(file),
+                                     FSCACHE_INVAL_DIO_WRITE);
+
 out:
        free_dentry_path(page);
        free_xid(xid);
@@ -876,6 +881,8 @@ int cifs_close(struct inode *inode, struct file *file)
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct cifs_deferred_close *dclose;
 
+       cifs_fscache_unuse_inode_cookie(inode, file->f_mode & FMODE_WRITE);
+
        if (file->private_data != NULL) {
                cfile = file->private_data;
                file->private_data = NULL;
@@ -886,7 +893,6 @@ int cifs_close(struct inode *inode, struct file *file)
                    dclose) {
                        if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
                                inode->i_ctime = inode->i_mtime = current_time(inode);
-                               cifs_fscache_update_inode_cookie(inode);
                        }
                        spin_lock(&cinode->deferred_lock);
                        cifs_add_deferred_close(cfile, dclose);
@@ -4198,10 +4204,12 @@ static vm_fault_t
 cifs_page_mkwrite(struct vm_fault *vmf)
 {
        struct page *page = vmf->page;
-       struct file *file = vmf->vma->vm_file;
-       struct inode *inode = file_inode(file);
 
-       cifs_fscache_wait_on_page_write(inode, page);
+#ifdef CONFIG_CIFS_FSCACHE
+       if (PageFsCache(page) &&
+           wait_on_page_fscache_killable(page) < 0)
+               return VM_FAULT_RETRY;
+#endif
 
        lock_page(page);
        return VM_FAULT_LOCKED;
@@ -4275,8 +4283,6 @@ cifs_readv_complete(struct work_struct *work)
                if (rdata->result == 0 ||
                    (rdata->result == -EAGAIN && got_bytes))
                        cifs_readpage_to_fscache(rdata->mapping->host, page);
-               else
-                       cifs_fscache_uncache_page(rdata->mapping->host, page);
 
                got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes);
 
@@ -4593,11 +4599,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                kref_put(&rdata->refcount, cifs_readdata_release);
        }
 
-       /* Any pages that have been shown to fscache but didn't get added to
-        * the pagecache must be uncached before they get returned to the
-        * allocator.
-        */
-       cifs_fscache_readpages_cancel(mapping->host, page_list);
        free_xid(xid);
        return rc;
 }
@@ -4801,17 +4802,19 @@ static int cifs_release_page(struct page *page, gfp_t gfp)
 {
        if (PagePrivate(page))
                return 0;
-
-       return cifs_fscache_release_page(page, gfp);
+       if (PageFsCache(page)) {
+               if (current_is_kswapd() || !(gfp & __GFP_FS))
+                       return false;
+               wait_on_page_fscache(page);
+       }
+       fscache_note_page_release(cifs_inode_cookie(page->mapping->host));
+       return true;
 }
 
 static void cifs_invalidate_page(struct page *page, unsigned int offset,
                                 unsigned int length)
 {
-       struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
-
-       if (offset == 0 && length == PAGE_SIZE)
-               cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
+       wait_on_page_fscache(page);
 }
 
 static int cifs_launder_page(struct page *page)
@@ -4831,7 +4834,7 @@ static int cifs_launder_page(struct page *page)
        if (clear_page_dirty_for_io(page))
                rc = cifs_writepage_locked(page, &wbc);
 
-       cifs_fscache_invalidate_page(page, page->mapping->host);
+       wait_on_page_fscache(page);
        return rc;
 }
 
@@ -4988,6 +4991,19 @@ static void cifs_swap_deactivate(struct file *file)
        /* do we need to unpin (or unlock) the file */
 }
 
+/*
+ * Mark a page as having been made dirty and thus needing writeback.  We also
+ * need to pin the cache object to write back to.
+ */
+#ifdef CONFIG_CIFS_FSCACHE
+static int cifs_set_page_dirty(struct page *page)
+{
+       return fscache_set_page_dirty(page, cifs_inode_cookie(page->mapping->host));
+}
+#else
+#define cifs_set_page_dirty __set_page_dirty_nobuffers
+#endif
+
 const struct address_space_operations cifs_addr_ops = {
        .readpage = cifs_readpage,
        .readpages = cifs_readpages,
@@ -4995,7 +5011,7 @@ const struct address_space_operations cifs_addr_ops = {
        .writepages = cifs_writepages,
        .write_begin = cifs_write_begin,
        .write_end = cifs_write_end,
-       .set_page_dirty = __set_page_dirty_nobuffers,
+       .set_page_dirty = cifs_set_page_dirty,
        .releasepage = cifs_release_page,
        .direct_IO = cifs_direct_io,
        .invalidatepage = cifs_invalidate_page,
@@ -5020,7 +5036,7 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
        .writepages = cifs_writepages,
        .write_begin = cifs_write_begin,
        .write_end = cifs_write_end,
-       .set_page_dirty = __set_page_dirty_nobuffers,
+       .set_page_dirty = cifs_set_page_dirty,
        .releasepage = cifs_release_page,
        .invalidatepage = cifs_invalidate_page,
        .launder_page = cifs_launder_page,