linux/fs/orangefs/inode.c
<<
>>
Prefs
   1/*
   2 * (C) 2001 Clemson University and The University of Chicago
   3 *
   4 * See COPYING in top-level directory.
   5 */
   6
   7/*
   8 *  Linux VFS inode operations.
   9 */
  10
  11#include <linux/bvec.h>
  12#include "protocol.h"
  13#include "orangefs-kernel.h"
  14#include "orangefs-bufmap.h"
  15
  16static int read_one_page(struct page *page)
  17{
  18        int ret;
  19        int max_block;
  20        ssize_t bytes_read = 0;
  21        struct inode *inode = page->mapping->host;
  22        const __u32 blocksize = PAGE_SIZE;      /* inode->i_blksize */
  23        const __u32 blockbits = PAGE_SHIFT;     /* inode->i_blkbits */
  24        struct iov_iter to;
  25        struct bio_vec bv = {.bv_page = page, .bv_len = PAGE_SIZE};
  26
  27        iov_iter_bvec(&to, ITER_BVEC | READ, &bv, 1, PAGE_SIZE);
  28
  29        gossip_debug(GOSSIP_INODE_DEBUG,
  30                    "orangefs_readpage called with page %p\n",
  31                     page);
  32
  33        max_block = ((inode->i_size / blocksize) + 1);
  34
  35        if (page->index < max_block) {
  36                loff_t blockptr_offset = (((loff_t) page->index) << blockbits);
  37
  38                bytes_read = orangefs_inode_read(inode,
  39                                                 &to,
  40                                                 &blockptr_offset,
  41                                                 inode->i_size);
  42        }
  43        /* this will only zero remaining unread portions of the page data */
  44        iov_iter_zero(~0U, &to);
  45        /* takes care of potential aliasing */
  46        flush_dcache_page(page);
  47        if (bytes_read < 0) {
  48                ret = bytes_read;
  49                SetPageError(page);
  50        } else {
  51                SetPageUptodate(page);
  52                if (PageError(page))
  53                        ClearPageError(page);
  54                ret = 0;
  55        }
  56        /* unlock the page after the ->readpage() routine completes */
  57        unlock_page(page);
  58        return ret;
  59}
  60
  61static int orangefs_readpage(struct file *file, struct page *page)
  62{
  63        return read_one_page(page);
  64}
  65
  66static int orangefs_readpages(struct file *file,
  67                           struct address_space *mapping,
  68                           struct list_head *pages,
  69                           unsigned nr_pages)
  70{
  71        int page_idx;
  72        int ret;
  73
  74        gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_readpages called\n");
  75
  76        for (page_idx = 0; page_idx < nr_pages; page_idx++) {
  77                struct page *page;
  78
  79                page = list_entry(pages->prev, struct page, lru);
  80                list_del(&page->lru);
  81                if (!add_to_page_cache(page,
  82                                       mapping,
  83                                       page->index,
  84                                       readahead_gfp_mask(mapping))) {
  85                        ret = read_one_page(page);
  86                        gossip_debug(GOSSIP_INODE_DEBUG,
  87                                "failure adding page to cache, read_one_page returned: %d\n",
  88                                ret);
  89              } else {
  90                        put_page(page);
  91              }
  92        }
  93        BUG_ON(!list_empty(pages));
  94        return 0;
  95}
  96
  97static void orangefs_invalidatepage(struct page *page,
  98                                 unsigned int offset,
  99                                 unsigned int length)
 100{
 101        gossip_debug(GOSSIP_INODE_DEBUG,
 102                     "orangefs_invalidatepage called on page %p "
 103                     "(offset is %u)\n",
 104                     page,
 105                     offset);
 106
 107        ClearPageUptodate(page);
 108        ClearPageMappedToDisk(page);
 109        return;
 110
 111}
 112
 113static int orangefs_releasepage(struct page *page, gfp_t foo)
 114{
 115        gossip_debug(GOSSIP_INODE_DEBUG,
 116                     "orangefs_releasepage called on page %p\n",
 117                     page);
 118        return 0;
 119}
 120
 121/*
 122 * Having a direct_IO entry point in the address_space_operations
 123 * struct causes the kernel to allows us to use O_DIRECT on
 124 * open. Nothing will ever call this thing, but in the future we
 125 * will need to be able to use O_DIRECT on open in order to support
 126 * AIO. Modeled after NFS, they do this too.
 127 */
 128
 129static ssize_t orangefs_direct_IO(struct kiocb *iocb,
 130                                  struct iov_iter *iter)
 131{
 132        gossip_debug(GOSSIP_INODE_DEBUG,
 133                     "orangefs_direct_IO: %pD\n",
 134                     iocb->ki_filp);
 135
 136        return -EINVAL;
 137}
 138
 139/** ORANGEFS2 implementation of address space operations */
 140const struct address_space_operations orangefs_address_operations = {
 141        .readpage = orangefs_readpage,
 142        .readpages = orangefs_readpages,
 143        .invalidatepage = orangefs_invalidatepage,
 144        .releasepage = orangefs_releasepage,
 145        .direct_IO = orangefs_direct_IO,
 146};
 147
 148static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
 149{
 150        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 151        struct orangefs_kernel_op_s *new_op;
 152        loff_t orig_size;
 153        int ret = -EINVAL;
 154
 155        gossip_debug(GOSSIP_INODE_DEBUG,
 156                     "%s: %pU: Handle is %pU | fs_id %d | size is %llu\n",
 157                     __func__,
 158                     get_khandle_from_ino(inode),
 159                     &orangefs_inode->refn.khandle,
 160                     orangefs_inode->refn.fs_id,
 161                     iattr->ia_size);
 162
 163        /* Ensure that we have a up to date size, so we know if it changed. */
 164        ret = orangefs_inode_getattr(inode, 0, 1, STATX_SIZE);
 165        if (ret == -ESTALE)
 166                ret = -EIO;
 167        if (ret) {
 168                gossip_err("%s: orangefs_inode_getattr failed, ret:%d:.\n",
 169                    __func__, ret);
 170                return ret;
 171        }
 172        orig_size = i_size_read(inode);
 173
 174        truncate_setsize(inode, iattr->ia_size);
 175
 176        new_op = op_alloc(ORANGEFS_VFS_OP_TRUNCATE);
 177        if (!new_op)
 178                return -ENOMEM;
 179
 180        new_op->upcall.req.truncate.refn = orangefs_inode->refn;
 181        new_op->upcall.req.truncate.size = (__s64) iattr->ia_size;
 182
 183        ret = service_operation(new_op, __func__,
 184                                get_interruptible_flag(inode));
 185
 186        /*
 187         * the truncate has no downcall members to retrieve, but
 188         * the status value tells us if it went through ok or not
 189         */
 190        gossip_debug(GOSSIP_INODE_DEBUG,
 191                     "orangefs: orangefs_truncate got return value of %d\n",
 192                     ret);
 193
 194        op_release(new_op);
 195
 196        if (ret != 0)
 197                return ret;
 198
 199        if (orig_size != i_size_read(inode))
 200                iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
 201
 202        return ret;
 203}
 204
 205/*
 206 * Change attributes of an object referenced by dentry.
 207 */
 208int orangefs_setattr(struct dentry *dentry, struct iattr *iattr)
 209{
 210        int ret = -EINVAL;
 211        struct inode *inode = dentry->d_inode;
 212
 213        gossip_debug(GOSSIP_INODE_DEBUG,
 214                     "orangefs_setattr: called on %pd\n",
 215                     dentry);
 216
 217        ret = setattr_prepare(dentry, iattr);
 218        if (ret)
 219                goto out;
 220
 221        if (iattr->ia_valid & ATTR_SIZE) {
 222                ret = orangefs_setattr_size(inode, iattr);
 223                if (ret)
 224                        goto out;
 225        }
 226
 227        setattr_copy(inode, iattr);
 228        mark_inode_dirty(inode);
 229
 230        ret = orangefs_inode_setattr(inode, iattr);
 231        gossip_debug(GOSSIP_INODE_DEBUG,
 232                     "orangefs_setattr: inode_setattr returned %d\n",
 233                     ret);
 234
 235        if (!ret && (iattr->ia_valid & ATTR_MODE))
 236                /* change mod on a file that has ACLs */
 237                ret = posix_acl_chmod(inode, inode->i_mode);
 238
 239out:
 240        gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_setattr: returning %d\n", ret);
 241        return ret;
 242}
 243
 244/*
 245 * Obtain attributes of an object given a dentry
 246 */
 247int orangefs_getattr(const struct path *path, struct kstat *stat,
 248                     u32 request_mask, unsigned int flags)
 249{
 250        int ret = -ENOENT;
 251        struct inode *inode = path->dentry->d_inode;
 252        struct orangefs_inode_s *orangefs_inode = NULL;
 253
 254        gossip_debug(GOSSIP_INODE_DEBUG,
 255                     "orangefs_getattr: called on %pd\n",
 256                     path->dentry);
 257
 258        ret = orangefs_inode_getattr(inode, 0, 0, request_mask);
 259        if (ret == 0) {
 260                generic_fillattr(inode, stat);
 261
 262                /* override block size reported to stat */
 263                orangefs_inode = ORANGEFS_I(inode);
 264                stat->blksize = orangefs_inode->blksize;
 265
 266                if (request_mask & STATX_SIZE)
 267                        stat->result_mask = STATX_BASIC_STATS;
 268                else
 269                        stat->result_mask = STATX_BASIC_STATS &
 270                            ~STATX_SIZE;
 271        }
 272        return ret;
 273}
 274
 275int orangefs_permission(struct inode *inode, int mask)
 276{
 277        int ret;
 278
 279        if (mask & MAY_NOT_BLOCK)
 280                return -ECHILD;
 281
 282        gossip_debug(GOSSIP_INODE_DEBUG, "%s: refreshing\n", __func__);
 283
 284        /* Make sure the permission (and other common attrs) are up to date. */
 285        ret = orangefs_inode_getattr(inode, 0, 0, STATX_MODE);
 286        if (ret < 0)
 287                return ret;
 288
 289        return generic_permission(inode, mask);
 290}
 291
 292/* ORANGEDS2 implementation of VFS inode operations for files */
 293const struct inode_operations orangefs_file_inode_operations = {
 294        .get_acl = orangefs_get_acl,
 295        .set_acl = orangefs_set_acl,
 296        .setattr = orangefs_setattr,
 297        .getattr = orangefs_getattr,
 298        .listxattr = orangefs_listxattr,
 299        .permission = orangefs_permission,
 300};
 301
 302static int orangefs_init_iops(struct inode *inode)
 303{
 304        inode->i_mapping->a_ops = &orangefs_address_operations;
 305
 306        switch (inode->i_mode & S_IFMT) {
 307        case S_IFREG:
 308                inode->i_op = &orangefs_file_inode_operations;
 309                inode->i_fop = &orangefs_file_operations;
 310                inode->i_blkbits = PAGE_SHIFT;
 311                break;
 312        case S_IFLNK:
 313                inode->i_op = &orangefs_symlink_inode_operations;
 314                break;
 315        case S_IFDIR:
 316                inode->i_op = &orangefs_dir_inode_operations;
 317                inode->i_fop = &orangefs_dir_operations;
 318                break;
 319        default:
 320                gossip_debug(GOSSIP_INODE_DEBUG,
 321                             "%s: unsupported mode\n",
 322                             __func__);
 323                return -EINVAL;
 324        }
 325
 326        return 0;
 327}
 328
 329/*
 330 * Given a ORANGEFS object identifier (fsid, handle), convert it into a ino_t type
 331 * that will be used as a hash-index from where the handle will
 332 * be searched for in the VFS hash table of inodes.
 333 */
 334static inline ino_t orangefs_handle_hash(struct orangefs_object_kref *ref)
 335{
 336        if (!ref)
 337                return 0;
 338        return orangefs_khandle_to_ino(&(ref->khandle));
 339}
 340
 341/*
 342 * Called to set up an inode from iget5_locked.
 343 */
 344static int orangefs_set_inode(struct inode *inode, void *data)
 345{
 346        struct orangefs_object_kref *ref = (struct orangefs_object_kref *) data;
 347        ORANGEFS_I(inode)->refn.fs_id = ref->fs_id;
 348        ORANGEFS_I(inode)->refn.khandle = ref->khandle;
 349        return 0;
 350}
 351
 352/*
 353 * Called to determine if handles match.
 354 */
 355static int orangefs_test_inode(struct inode *inode, void *data)
 356{
 357        struct orangefs_object_kref *ref = (struct orangefs_object_kref *) data;
 358        struct orangefs_inode_s *orangefs_inode = NULL;
 359
 360        orangefs_inode = ORANGEFS_I(inode);
 361        return (!ORANGEFS_khandle_cmp(&(orangefs_inode->refn.khandle), &(ref->khandle))
 362                && orangefs_inode->refn.fs_id == ref->fs_id);
 363}
 364
 365/*
 366 * Front-end to lookup the inode-cache maintained by the VFS using the ORANGEFS
 367 * file handle.
 368 *
 369 * @sb: the file system super block instance.
 370 * @ref: The ORANGEFS object for which we are trying to locate an inode structure.
 371 */
 372struct inode *orangefs_iget(struct super_block *sb, struct orangefs_object_kref *ref)
 373{
 374        struct inode *inode = NULL;
 375        unsigned long hash;
 376        int error;
 377
 378        hash = orangefs_handle_hash(ref);
 379        inode = iget5_locked(sb, hash, orangefs_test_inode, orangefs_set_inode, ref);
 380        if (!inode || !(inode->i_state & I_NEW))
 381                return inode;
 382
 383        error = orangefs_inode_getattr(inode, 1, 1, STATX_ALL);
 384        if (error) {
 385                iget_failed(inode);
 386                return ERR_PTR(error);
 387        }
 388
 389        inode->i_ino = hash;    /* needed for stat etc */
 390        orangefs_init_iops(inode);
 391        unlock_new_inode(inode);
 392
 393        gossip_debug(GOSSIP_INODE_DEBUG,
 394                     "iget handle %pU, fsid %d hash %ld i_ino %lu\n",
 395                     &ref->khandle,
 396                     ref->fs_id,
 397                     hash,
 398                     inode->i_ino);
 399
 400        return inode;
 401}
 402
 403/*
 404 * Allocate an inode for a newly created file and insert it into the inode hash.
 405 */
 406struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
 407                int mode, dev_t dev, struct orangefs_object_kref *ref)
 408{
 409        unsigned long hash = orangefs_handle_hash(ref);
 410        struct inode *inode;
 411        int error;
 412
 413        gossip_debug(GOSSIP_INODE_DEBUG,
 414                     "%s:(sb is %p | MAJOR(dev)=%u | MINOR(dev)=%u mode=%o)\n",
 415                     __func__,
 416                     sb,
 417                     MAJOR(dev),
 418                     MINOR(dev),
 419                     mode);
 420
 421        inode = new_inode(sb);
 422        if (!inode)
 423                return NULL;
 424
 425        orangefs_set_inode(inode, ref);
 426        inode->i_ino = hash;    /* needed for stat etc */
 427
 428        error = orangefs_inode_getattr(inode, 1, 1, STATX_ALL);
 429        if (error)
 430                goto out_iput;
 431
 432        orangefs_init_iops(inode);
 433
 434        inode->i_mode = mode;
 435        inode->i_uid = current_fsuid();
 436        inode->i_gid = current_fsgid();
 437        inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
 438        inode->i_size = PAGE_SIZE;
 439        inode->i_rdev = dev;
 440
 441        error = insert_inode_locked4(inode, hash, orangefs_test_inode, ref);
 442        if (error < 0)
 443                goto out_iput;
 444
 445        gossip_debug(GOSSIP_INODE_DEBUG,
 446                     "Initializing ACL's for inode %pU\n",
 447                     get_khandle_from_ino(inode));
 448        orangefs_init_acl(inode, dir);
 449        return inode;
 450
 451out_iput:
 452        iput(inode);
 453        return ERR_PTR(error);
 454}
 455