linux/fs/afs/file.c
<<
>>
Prefs
   1/* AFS filesystem file handling
   2 *
   3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
   4 * Written by David Howells (dhowells@redhat.com)
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License
   8 * as published by the Free Software Foundation; either version
   9 * 2 of the License, or (at your option) any later version.
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/module.h>
  14#include <linux/init.h>
  15#include <linux/fs.h>
  16#include <linux/pagemap.h>
  17#include <linux/writeback.h>
  18#include <linux/gfp.h>
  19#include "internal.h"
  20
  21static int afs_readpage(struct file *file, struct page *page);
  22static void afs_invalidatepage(struct page *page, unsigned int offset,
  23                               unsigned int length);
  24static int afs_releasepage(struct page *page, gfp_t gfp_flags);
  25static int afs_launder_page(struct page *page);
  26
  27static int afs_readpages(struct file *filp, struct address_space *mapping,
  28                         struct list_head *pages, unsigned nr_pages);
  29
  30const struct file_operations afs_file_operations = {
  31        .open           = afs_open,
  32        .release        = afs_release,
  33        .llseek         = generic_file_llseek,
  34        .read           = do_sync_read,
  35        .write          = do_sync_write,
  36        .aio_read       = generic_file_aio_read,
  37        .aio_write      = afs_file_write,
  38        .mmap           = generic_file_readonly_mmap,
  39        .splice_read    = generic_file_splice_read,
  40        .fsync          = afs_fsync,
  41        .lock           = afs_lock,
  42        .flock          = afs_flock,
  43};
  44
  45const struct inode_operations afs_file_inode_operations = {
  46        .getattr        = afs_getattr,
  47        .setattr        = afs_setattr,
  48        .permission     = afs_permission,
  49};
  50
  51const struct address_space_operations afs_fs_aops = {
  52        .readpage       = afs_readpage,
  53        .readpages      = afs_readpages,
  54        .set_page_dirty = afs_set_page_dirty,
  55        .launder_page   = afs_launder_page,
  56        .releasepage    = afs_releasepage,
  57        .invalidatepage = afs_invalidatepage,
  58        .write_begin    = afs_write_begin,
  59        .write_end      = afs_write_end,
  60        .writepage      = afs_writepage,
  61        .writepages     = afs_writepages,
  62};
  63
  64/*
  65 * open an AFS file or directory and attach a key to it
  66 */
  67int afs_open(struct inode *inode, struct file *file)
  68{
  69        struct afs_vnode *vnode = AFS_FS_I(inode);
  70        struct key *key;
  71        int ret;
  72
  73        _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
  74
  75        key = afs_request_key(vnode->volume->cell);
  76        if (IS_ERR(key)) {
  77                _leave(" = %ld [key]", PTR_ERR(key));
  78                return PTR_ERR(key);
  79        }
  80
  81        ret = afs_validate(vnode, key);
  82        if (ret < 0) {
  83                _leave(" = %d [val]", ret);
  84                return ret;
  85        }
  86
  87        file->private_data = key;
  88        _leave(" = 0");
  89        return 0;
  90}
  91
  92/*
  93 * release an AFS file or directory and discard its key
  94 */
  95int afs_release(struct inode *inode, struct file *file)
  96{
  97        struct afs_vnode *vnode = AFS_FS_I(inode);
  98
  99        _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
 100
 101        key_put(file->private_data);
 102        _leave(" = 0");
 103        return 0;
 104}
 105
 106#ifdef CONFIG_AFS_FSCACHE
 107/*
 108 * deal with notification that a page was read from the cache
 109 */
 110static void afs_file_readpage_read_complete(struct page *page,
 111                                            void *data,
 112                                            int error)
 113{
 114        _enter("%p,%p,%d", page, data, error);
 115
 116        /* if the read completes with an error, we just unlock the page and let
 117         * the VM reissue the readpage */
 118        if (!error)
 119                SetPageUptodate(page);
 120        unlock_page(page);
 121}
 122#endif
 123
 124/*
 125 * read page from file, directory or symlink, given a key to use
 126 */
 127int afs_page_filler(void *data, struct page *page)
 128{
 129        struct inode *inode = page->mapping->host;
 130        struct afs_vnode *vnode = AFS_FS_I(inode);
 131        struct key *key = data;
 132        size_t len;
 133        off_t offset;
 134        int ret;
 135
 136        _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index);
 137
 138        BUG_ON(!PageLocked(page));
 139
 140        ret = -ESTALE;
 141        if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
 142                goto error;
 143
 144        /* is it cached? */
 145#ifdef CONFIG_AFS_FSCACHE
 146        ret = fscache_read_or_alloc_page(vnode->cache,
 147                                         page,
 148                                         afs_file_readpage_read_complete,
 149                                         NULL,
 150                                         GFP_KERNEL);
 151#else
 152        ret = -ENOBUFS;
 153#endif
 154        switch (ret) {
 155                /* read BIO submitted (page in cache) */
 156        case 0:
 157                break;
 158
 159                /* page not yet cached */
 160        case -ENODATA:
 161                _debug("cache said ENODATA");
 162                goto go_on;
 163
 164                /* page will not be cached */
 165        case -ENOBUFS:
 166                _debug("cache said ENOBUFS");
 167        default:
 168        go_on:
 169                offset = page->index << PAGE_CACHE_SHIFT;
 170                len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE);
 171
 172                /* read the contents of the file from the server into the
 173                 * page */
 174                ret = afs_vnode_fetch_data(vnode, key, offset, len, page);
 175                if (ret < 0) {
 176                        if (ret == -ENOENT) {
 177                                _debug("got NOENT from server"
 178                                       " - marking file deleted and stale");
 179                                set_bit(AFS_VNODE_DELETED, &vnode->flags);
 180                                ret = -ESTALE;
 181                        }
 182
 183#ifdef CONFIG_AFS_FSCACHE
 184                        fscache_uncache_page(vnode->cache, page);
 185#endif
 186                        BUG_ON(PageFsCache(page));
 187                        goto error;
 188                }
 189
 190                SetPageUptodate(page);
 191
 192                /* send the page to the cache */
 193#ifdef CONFIG_AFS_FSCACHE
 194                if (PageFsCache(page) &&
 195                    fscache_write_page(vnode->cache, page, GFP_KERNEL) != 0) {
 196                        fscache_uncache_page(vnode->cache, page);
 197                        BUG_ON(PageFsCache(page));
 198                }
 199#endif
 200                unlock_page(page);
 201        }
 202
 203        _leave(" = 0");
 204        return 0;
 205
 206error:
 207        SetPageError(page);
 208        unlock_page(page);
 209        _leave(" = %d", ret);
 210        return ret;
 211}
 212
 213/*
 214 * read page from file, directory or symlink, given a file to nominate the key
 215 * to be used
 216 */
 217static int afs_readpage(struct file *file, struct page *page)
 218{
 219        struct key *key;
 220        int ret;
 221
 222        if (file) {
 223                key = file->private_data;
 224                ASSERT(key != NULL);
 225                ret = afs_page_filler(key, page);
 226        } else {
 227                struct inode *inode = page->mapping->host;
 228                key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell);
 229                if (IS_ERR(key)) {
 230                        ret = PTR_ERR(key);
 231                } else {
 232                        ret = afs_page_filler(key, page);
 233                        key_put(key);
 234                }
 235        }
 236        return ret;
 237}
 238
 239/*
 240 * read a set of pages
 241 */
 242static int afs_readpages(struct file *file, struct address_space *mapping,
 243                         struct list_head *pages, unsigned nr_pages)
 244{
 245        struct key *key = file->private_data;
 246        struct afs_vnode *vnode;
 247        int ret = 0;
 248
 249        _enter("{%d},{%lu},,%d",
 250               key_serial(key), mapping->host->i_ino, nr_pages);
 251
 252        ASSERT(key != NULL);
 253
 254        vnode = AFS_FS_I(mapping->host);
 255        if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
 256                _leave(" = -ESTALE");
 257                return -ESTALE;
 258        }
 259
 260        /* attempt to read as many of the pages as possible */
 261#ifdef CONFIG_AFS_FSCACHE
 262        ret = fscache_read_or_alloc_pages(vnode->cache,
 263                                          mapping,
 264                                          pages,
 265                                          &nr_pages,
 266                                          afs_file_readpage_read_complete,
 267                                          NULL,
 268                                          mapping_gfp_mask(mapping));
 269#else
 270        ret = -ENOBUFS;
 271#endif
 272
 273        switch (ret) {
 274                /* all pages are being read from the cache */
 275        case 0:
 276                BUG_ON(!list_empty(pages));
 277                BUG_ON(nr_pages != 0);
 278                _leave(" = 0 [reading all]");
 279                return 0;
 280
 281                /* there were pages that couldn't be read from the cache */
 282        case -ENODATA:
 283        case -ENOBUFS:
 284                break;
 285
 286                /* other error */
 287        default:
 288                _leave(" = %d", ret);
 289                return ret;
 290        }
 291
 292        /* load the missing pages from the network */
 293        ret = read_cache_pages(mapping, pages, afs_page_filler, key);
 294
 295        _leave(" = %d [netting]", ret);
 296        return ret;
 297}
 298
 299/*
 300 * write back a dirty page
 301 */
 302static int afs_launder_page(struct page *page)
 303{
 304        _enter("{%lu}", page->index);
 305
 306        return 0;
 307}
 308
 309/*
 310 * invalidate part or all of a page
 311 * - release a page and clean up its private data if offset is 0 (indicating
 312 *   the entire page)
 313 */
 314static void afs_invalidatepage(struct page *page, unsigned int offset,
 315                               unsigned int length)
 316{
 317        struct afs_writeback *wb = (struct afs_writeback *) page_private(page);
 318
 319        _enter("{%lu},%u,%u", page->index, offset, length);
 320
 321        BUG_ON(!PageLocked(page));
 322
 323        /* we clean up only if the entire page is being invalidated */
 324        if (offset == 0 && length == PAGE_CACHE_SIZE) {
 325#ifdef CONFIG_AFS_FSCACHE
 326                if (PageFsCache(page)) {
 327                        struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
 328                        fscache_wait_on_page_write(vnode->cache, page);
 329                        fscache_uncache_page(vnode->cache, page);
 330                }
 331#endif
 332
 333                if (PagePrivate(page)) {
 334                        if (wb && !PageWriteback(page)) {
 335                                set_page_private(page, 0);
 336                                afs_put_writeback(wb);
 337                        }
 338
 339                        if (!page_private(page))
 340                                ClearPagePrivate(page);
 341                }
 342        }
 343
 344        _leave("");
 345}
 346
 347/*
 348 * release a page and clean up its private state if it's not busy
 349 * - return true if the page can now be released, false if not
 350 */
 351static int afs_releasepage(struct page *page, gfp_t gfp_flags)
 352{
 353        struct afs_writeback *wb = (struct afs_writeback *) page_private(page);
 354        struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
 355
 356        _enter("{{%x:%u}[%lu],%lx},%x",
 357               vnode->fid.vid, vnode->fid.vnode, page->index, page->flags,
 358               gfp_flags);
 359
 360        /* deny if page is being written to the cache and the caller hasn't
 361         * elected to wait */
 362#ifdef CONFIG_AFS_FSCACHE
 363        if (!fscache_maybe_release_page(vnode->cache, page, gfp_flags)) {
 364                _leave(" = F [cache busy]");
 365                return 0;
 366        }
 367#endif
 368
 369        if (PagePrivate(page)) {
 370                if (wb) {
 371                        set_page_private(page, 0);
 372                        afs_put_writeback(wb);
 373                }
 374                ClearPagePrivate(page);
 375        }
 376
 377        /* indicate that the page can be released */
 378        _leave(" = T");
 379        return 1;
 380}
 381
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.