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