linux/fs/cifs/fscache.c
<<
>>
Prefs
   1/*
   2 *   fs/cifs/fscache.c - CIFS filesystem cache interface
   3 *
   4 *   Copyright (c) 2010 Novell, Inc.
   5 *   Author(s): Suresh Jayaraman <sjayaraman@suse.de>
   6 *
   7 *   This library is free software; you can redistribute it and/or modify
   8 *   it under the terms of the GNU Lesser General Public License as published
   9 *   by the Free Software Foundation; either version 2.1 of the License, or
  10 *   (at your option) any later version.
  11 *
  12 *   This library is distributed in the hope that it will be useful,
  13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  15 *   the GNU Lesser General Public License for more details.
  16 *
  17 *   You should have received a copy of the GNU Lesser General Public License
  18 *   along with this library; if not, write to the Free Software
  19 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 */
  21#include "fscache.h"
  22#include "cifsglob.h"
  23#include "cifs_debug.h"
  24#include "cifs_fs_sb.h"
  25
  26void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
  27{
  28        server->fscache =
  29                fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
  30                                &cifs_fscache_server_index_def, server, true);
  31        cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
  32                 __func__, server, server->fscache);
  33}
  34
  35void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
  36{
  37        cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
  38                 __func__, server, server->fscache);
  39        fscache_relinquish_cookie(server->fscache, 0);
  40        server->fscache = NULL;
  41}
  42
  43void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
  44{
  45        struct TCP_Server_Info *server = tcon->ses->server;
  46
  47        tcon->fscache =
  48                fscache_acquire_cookie(server->fscache,
  49                                &cifs_fscache_super_index_def, tcon, true);
  50        cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
  51                 __func__, server->fscache, tcon->fscache);
  52}
  53
  54void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
  55{
  56        cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
  57        fscache_relinquish_cookie(tcon->fscache, 0);
  58        tcon->fscache = NULL;
  59}
  60
  61static void cifs_fscache_enable_inode_cookie(struct inode *inode)
  62{
  63        struct cifsInodeInfo *cifsi = CIFS_I(inode);
  64        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
  65        struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
  66
  67        if (cifsi->fscache)
  68                return;
  69
  70        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) {
  71                cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
  72                                &cifs_fscache_inode_object_def, cifsi, true);
  73                cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)\n",
  74                         __func__, tcon->fscache, cifsi->fscache);
  75        }
  76}
  77
  78void cifs_fscache_release_inode_cookie(struct inode *inode)
  79{
  80        struct cifsInodeInfo *cifsi = CIFS_I(inode);
  81
  82        if (cifsi->fscache) {
  83                cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
  84                fscache_relinquish_cookie(cifsi->fscache, 0);
  85                cifsi->fscache = NULL;
  86        }
  87}
  88
  89static void cifs_fscache_disable_inode_cookie(struct inode *inode)
  90{
  91        struct cifsInodeInfo *cifsi = CIFS_I(inode);
  92
  93        if (cifsi->fscache) {
  94                cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
  95                fscache_uncache_all_inode_pages(cifsi->fscache, inode);
  96                fscache_relinquish_cookie(cifsi->fscache, 1);
  97                cifsi->fscache = NULL;
  98        }
  99}
 100
 101void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp)
 102{
 103        if ((filp->f_flags & O_ACCMODE) != O_RDONLY)
 104                cifs_fscache_disable_inode_cookie(inode);
 105        else
 106                cifs_fscache_enable_inode_cookie(inode);
 107}
 108
 109void cifs_fscache_reset_inode_cookie(struct inode *inode)
 110{
 111        struct cifsInodeInfo *cifsi = CIFS_I(inode);
 112        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 113        struct fscache_cookie *old = cifsi->fscache;
 114
 115        if (cifsi->fscache) {
 116                /* retire the current fscache cache and get a new one */
 117                fscache_relinquish_cookie(cifsi->fscache, 1);
 118
 119                cifsi->fscache = fscache_acquire_cookie(
 120                                        cifs_sb_master_tcon(cifs_sb)->fscache,
 121                                        &cifs_fscache_inode_object_def,
 122                                        cifsi, true);
 123                cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p\n",
 124                         __func__, cifsi->fscache, old);
 125        }
 126}
 127
 128int cifs_fscache_release_page(struct page *page, gfp_t gfp)
 129{
 130        if (PageFsCache(page)) {
 131                struct inode *inode = page->mapping->host;
 132                struct cifsInodeInfo *cifsi = CIFS_I(inode);
 133
 134                cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
 135                         __func__, page, cifsi->fscache);
 136                if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
 137                        return 0;
 138        }
 139
 140        return 1;
 141}
 142
 143static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx,
 144                                                int error)
 145{
 146        cifs_dbg(FYI, "%s: (0x%p/%d)\n", __func__, page, error);
 147        if (!error)
 148                SetPageUptodate(page);
 149        unlock_page(page);
 150}
 151
 152/*
 153 * Retrieve a page from FS-Cache
 154 */
 155int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
 156{
 157        int ret;
 158
 159        cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n",
 160                 __func__, CIFS_I(inode)->fscache, page, inode);
 161        ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page,
 162                                         cifs_readpage_from_fscache_complete,
 163                                         NULL,
 164                                         GFP_KERNEL);
 165        switch (ret) {
 166
 167        case 0: /* page found in fscache, read submitted */
 168                cifs_dbg(FYI, "%s: submitted\n", __func__);
 169                return ret;
 170        case -ENOBUFS:  /* page won't be cached */
 171        case -ENODATA:  /* page not in cache */
 172                cifs_dbg(FYI, "%s: %d\n", __func__, ret);
 173                return 1;
 174
 175        default:
 176                cifs_dbg(VFS, "unknown error ret = %d\n", ret);
 177        }
 178        return ret;
 179}
 180
 181/*
 182 * Retrieve a set of pages from FS-Cache
 183 */
 184int __cifs_readpages_from_fscache(struct inode *inode,
 185                                struct address_space *mapping,
 186                                struct list_head *pages,
 187                                unsigned *nr_pages)
 188{
 189        int ret;
 190
 191        cifs_dbg(FYI, "%s: (0x%p/%u/0x%p)\n",
 192                 __func__, CIFS_I(inode)->fscache, *nr_pages, inode);
 193        ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping,
 194                                          pages, nr_pages,
 195                                          cifs_readpage_from_fscache_complete,
 196                                          NULL,
 197                                          mapping_gfp_mask(mapping));
 198        switch (ret) {
 199        case 0: /* read submitted to the cache for all pages */
 200                cifs_dbg(FYI, "%s: submitted\n", __func__);
 201                return ret;
 202
 203        case -ENOBUFS:  /* some pages are not cached and can't be */
 204        case -ENODATA:  /* some pages are not cached */
 205                cifs_dbg(FYI, "%s: no page\n", __func__);
 206                return 1;
 207
 208        default:
 209                cifs_dbg(FYI, "unknown error ret = %d\n", ret);
 210        }
 211
 212        return ret;
 213}
 214
 215void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
 216{
 217        int ret;
 218
 219        cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n",
 220                 __func__, CIFS_I(inode)->fscache, page, inode);
 221        ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL);
 222        if (ret != 0)
 223                fscache_uncache_page(CIFS_I(inode)->fscache, page);
 224}
 225
 226void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_head *pages)
 227{
 228        cifs_dbg(FYI, "%s: (fsc: %p, i: %p)\n",
 229                 __func__, CIFS_I(inode)->fscache, inode);
 230        fscache_readpages_cancel(CIFS_I(inode)->fscache, pages);
 231}
 232
 233void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
 234{
 235        struct cifsInodeInfo *cifsi = CIFS_I(inode);
 236        struct fscache_cookie *cookie = cifsi->fscache;
 237
 238        cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie);
 239        fscache_wait_on_page_write(cookie, page);
 240        fscache_uncache_page(cookie, page);
 241}
 242
 243