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: %s\n",
 133                     iocb->ki_filp->f_path.dentry->d_name.name);
 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 %s\n",
 220                     dentry->d_name.name);
 221
 222        ret = inode_change_ok(inode, 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 %s\n",
 263                     dentry->d_name.name);
 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        .setxattr = generic_setxattr,
 300        .getxattr = generic_getxattr,
 301        .listxattr = orangefs_listxattr,
 302        .removexattr = generic_removexattr,
 303        .permission = orangefs_permission,
 304};
 305
 306static int orangefs_init_iops(struct inode *inode)
 307{
 308        inode->i_mapping->a_ops = &orangefs_address_operations;
 309
 310        switch (inode->i_mode & S_IFMT) {
 311        case S_IFREG:
 312                inode->i_op = &orangefs_file_inode_operations;
 313                inode->i_fop = &orangefs_file_operations;
 314                inode->i_blkbits = PAGE_SHIFT;
 315                break;
 316        case S_IFLNK:
 317                inode->i_op = &orangefs_symlink_inode_operations;
 318                break;
 319        case S_IFDIR:
 320                inode->i_op = &orangefs_dir_inode_operations;
 321                inode->i_fop = &orangefs_dir_operations;
 322                break;
 323        default:
 324                gossip_debug(GOSSIP_INODE_DEBUG,
 325                             "%s: unsupported mode\n",
 326                             __func__);
 327                return -EINVAL;
 328        }
 329
 330        return 0;
 331}
 332
 333/*
 334 * Given a ORANGEFS object identifier (fsid, handle), convert it into a ino_t type
 335 * that will be used as a hash-index from where the handle will
 336 * be searched for in the VFS hash table of inodes.
 337 */
 338static inline ino_t orangefs_handle_hash(struct orangefs_object_kref *ref)
 339{
 340        if (!ref)
 341                return 0;
 342        return orangefs_khandle_to_ino(&(ref->khandle));
 343}
 344
 345/*
 346 * Called to set up an inode from iget5_locked.
 347 */
 348static int orangefs_set_inode(struct inode *inode, void *data)
 349{
 350        struct orangefs_object_kref *ref = (struct orangefs_object_kref *) data;
 351        ORANGEFS_I(inode)->refn.fs_id = ref->fs_id;
 352        ORANGEFS_I(inode)->refn.khandle = ref->khandle;
 353        return 0;
 354}
 355
 356/*
 357 * Called to determine if handles match.
 358 */
 359static int orangefs_test_inode(struct inode *inode, void *data)
 360{
 361        struct orangefs_object_kref *ref = (struct orangefs_object_kref *) data;
 362        struct orangefs_inode_s *orangefs_inode = NULL;
 363
 364        orangefs_inode = ORANGEFS_I(inode);
 365        return (!ORANGEFS_khandle_cmp(&(orangefs_inode->refn.khandle), &(ref->khandle))
 366                && orangefs_inode->refn.fs_id == ref->fs_id);
 367}
 368
 369/*
 370 * Front-end to lookup the inode-cache maintained by the VFS using the ORANGEFS
 371 * file handle.
 372 *
 373 * @sb: the file system super block instance.
 374 * @ref: The ORANGEFS object for which we are trying to locate an inode structure.
 375 */
 376struct inode *orangefs_iget(struct super_block *sb, struct orangefs_object_kref *ref)
 377{
 378        struct inode *inode = NULL;
 379        unsigned long hash;
 380        int error;
 381
 382        hash = orangefs_handle_hash(ref);
 383        inode = iget5_locked(sb, hash, orangefs_test_inode, orangefs_set_inode, ref);
 384        if (!inode || !(inode->i_state & I_NEW))
 385                return inode;
 386
 387        error = orangefs_inode_getattr(inode, 1, 1);
 388        if (error) {
 389                iget_failed(inode);
 390                return ERR_PTR(error);
 391        }
 392
 393        inode->i_ino = hash;    /* needed for stat etc */
 394        orangefs_init_iops(inode);
 395        unlock_new_inode(inode);
 396
 397        gossip_debug(GOSSIP_INODE_DEBUG,
 398                     "iget handle %pU, fsid %d hash %ld i_ino %lu\n",
 399                     &ref->khandle,
 400                     ref->fs_id,
 401                     hash,
 402                     inode->i_ino);
 403
 404        return inode;
 405}
 406
 407/*
 408 * Allocate an inode for a newly created file and insert it into the inode hash.
 409 */
 410struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
 411                int mode, dev_t dev, struct orangefs_object_kref *ref)
 412{
 413        unsigned long hash = orangefs_handle_hash(ref);
 414        struct inode *inode;
 415        int error;
 416
 417        gossip_debug(GOSSIP_INODE_DEBUG,
 418                     "%s:(sb is %p | MAJOR(dev)=%u | MINOR(dev)=%u mode=%o)\n",
 419                     __func__,
 420                     sb,
 421                     MAJOR(dev),
 422                     MINOR(dev),
 423                     mode);
 424
 425        inode = new_inode(sb);
 426        if (!inode)
 427                return NULL;
 428
 429        orangefs_set_inode(inode, ref);
 430        inode->i_ino = hash;    /* needed for stat etc */
 431
 432        error = orangefs_inode_getattr(inode, 1, 1);
 433        if (error)
 434                goto out_iput;
 435
 436        orangefs_init_iops(inode);
 437
 438        inode->i_mode = mode;
 439        inode->i_uid = current_fsuid();
 440        inode->i_gid = current_fsgid();
 441        inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
 442        inode->i_size = PAGE_SIZE;
 443        inode->i_rdev = dev;
 444
 445        error = insert_inode_locked4(inode, hash, orangefs_test_inode, ref);
 446        if (error < 0)
 447                goto out_iput;
 448
 449        gossip_debug(GOSSIP_INODE_DEBUG,
 450                     "Initializing ACL's for inode %pU\n",
 451                     get_khandle_from_ino(inode));
 452        orangefs_init_acl(inode, dir);
 453        return inode;
 454
 455out_iput:
 456        iput(inode);
 457        return ERR_PTR(error);
 458}
 459