]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/cifs/file.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
[karo-tx-linux.git] / fs / cifs / file.c
index d302d941f9acd0e035a0c0b7e947b8b7fe9e224f..db11fdef0e92b1ca52a75fb033f03dda24e8f6a5 100644 (file)
@@ -1944,6 +1944,9 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
                SetPageUptodate(page);
                unlock_page(page);
                data += PAGE_CACHE_SIZE;
+
+               /* add page to FS-Cache */
+               cifs_readpage_to_fscache(mapping->host, page);
        }
        return;
 }
@@ -1974,6 +1977,15 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
        cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
        pTcon = cifs_sb->tcon;
 
+       /*
+        * Reads as many pages as possible from fscache. Returns -ENOBUFS
+        * immediately if the cookie is negative
+        */
+       rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list,
+                                        &num_pages);
+       if (rc == 0)
+               goto read_complete;
+
        cFYI(DBG2, "rpages: num pages %d", num_pages);
        for (i = 0; i < num_pages; ) {
                unsigned contig_pages;
@@ -2084,6 +2096,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                smb_read_data = NULL;
        }
 
+read_complete:
        FreeXid(xid);
        return rc;
 }
@@ -2094,6 +2107,11 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
        char *read_data;
        int rc;
 
+       /* Is the page cached? */
+       rc = cifs_readpage_from_fscache(file->f_path.dentry->d_inode, page);
+       if (rc == 0)
+               goto read_complete;
+
        page_cache_get(page);
        read_data = kmap(page);
        /* for reads over a certain size could initiate async read ahead */
@@ -2113,11 +2131,17 @@ static int cifs_readpage_worker(struct file *file, struct page *page,
 
        flush_dcache_page(page);
        SetPageUptodate(page);
+
+       /* send this page to the cache */
+       cifs_readpage_to_fscache(file->f_path.dentry->d_inode, page);
+
        rc = 0;
 
 io_error:
        kunmap(page);
        page_cache_release(page);
+
+read_complete:
        return rc;
 }
 
@@ -2267,8 +2291,23 @@ out:
        return rc;
 }
 
-static void
-cifs_oplock_break(struct slow_work *work)
+static int cifs_release_page(struct page *page, gfp_t gfp)
+{
+       if (PagePrivate(page))
+               return 0;
+
+       return cifs_fscache_release_page(page, gfp);
+}
+
+static void cifs_invalidate_page(struct page *page, unsigned long offset)
+{
+       struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host);
+
+       if (offset == 0)
+               cifs_fscache_invalidate_page(page, &cifsi->vfs_inode);
+}
+
+void cifs_oplock_break(struct work_struct *work)
 {
        struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
                                                  oplock_break);
@@ -2305,33 +2344,30 @@ cifs_oplock_break(struct slow_work *work)
                                 LOCKING_ANDX_OPLOCK_RELEASE, false);
                cFYI(1, "Oplock release rc = %d", rc);
        }
+
+       /*
+        * We might have kicked in before is_valid_oplock_break()
+        * finished grabbing reference for us.  Make sure it's done by
+        * waiting for GlobalSMSSeslock.
+        */
+       write_lock(&GlobalSMBSeslock);
+       write_unlock(&GlobalSMBSeslock);
+
+       cifs_oplock_break_put(cfile);
 }
 
-static int
-cifs_oplock_break_get(struct slow_work *work)
+void cifs_oplock_break_get(struct cifsFileInfo *cfile)
 {
-       struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
-                                                 oplock_break);
        mntget(cfile->mnt);
        cifsFileInfo_get(cfile);
-       return 0;
 }
 
-static void
-cifs_oplock_break_put(struct slow_work *work)
+void cifs_oplock_break_put(struct cifsFileInfo *cfile)
 {
-       struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
-                                                 oplock_break);
        mntput(cfile->mnt);
        cifsFileInfo_put(cfile);
 }
 
-const struct slow_work_ops cifs_oplock_break_ops = {
-       .get_ref        = cifs_oplock_break_get,
-       .put_ref        = cifs_oplock_break_put,
-       .execute        = cifs_oplock_break,
-};
-
 const struct address_space_operations cifs_addr_ops = {
        .readpage = cifs_readpage,
        .readpages = cifs_readpages,
@@ -2340,6 +2376,8 @@ const struct address_space_operations cifs_addr_ops = {
        .write_begin = cifs_write_begin,
        .write_end = cifs_write_end,
        .set_page_dirty = __set_page_dirty_nobuffers,
+       .releasepage = cifs_release_page,
+       .invalidatepage = cifs_invalidate_page,
        /* .sync_page = cifs_sync_page, */
        /* .direct_IO = */
 };
@@ -2356,6 +2394,8 @@ const struct address_space_operations cifs_addr_ops_smallbuf = {
        .write_begin = cifs_write_begin,
        .write_end = cifs_write_end,
        .set_page_dirty = __set_page_dirty_nobuffers,
+       .releasepage = cifs_release_page,
+       .invalidatepage = cifs_invalidate_page,
        /* .sync_page = cifs_sync_page, */
        /* .direct_IO = */
 };