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