orangefs: rename orangefs_inode_getattr to orangefs_inode_old_getattr
authorMartin Brandenburg <martin@omnibond.com>
Tue, 15 Mar 2016 15:28:20 +0000 (11:28 -0400)
committerMike Marshall <hubcap@omnibond.com>
Wed, 23 Mar 2016 21:36:14 +0000 (17:36 -0400)
This is motivated by orangefs_inode_old_getattr's habit of writing over
live inodes.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
fs/orangefs/dcache.c
fs/orangefs/file.c
fs/orangefs/inode.c
fs/orangefs/orangefs-kernel.h
fs/orangefs/orangefs-utils.c

index 2de92b7..cc5487a 100644 (file)
@@ -117,7 +117,7 @@ static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
 
        /* Now we must perform a getattr to validate the inode contents. */
 
-       ret = orangefs_inode_getattr(dentry->d_inode,
+       ret = orangefs_inode_old_getattr(dentry->d_inode,
            ORANGEFS_ATTR_SYS_TYPE|ORANGEFS_ATTR_SYS_LNK_TARGET, 1);
        if (ret < 0) {
                gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n",
index 9b561b7..3aff671 100644 (file)
@@ -455,10 +455,10 @@ static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *ite
 
        /* Make sure generic_write_checks sees an up to date inode size. */
        if (file->f_flags & O_APPEND) {
-               rc = orangefs_inode_getattr(file->f_mapping->host,
+               rc = orangefs_inode_old_getattr(file->f_mapping->host,
                                         ORANGEFS_ATTR_SYS_SIZE, 0);
                if (rc) {
-                       gossip_err("%s: orangefs_inode_getattr failed, rc:%zd:.\n",
+                       gossip_err("%s: orangefs_inode_old_getattr failed, rc:%zd:.\n",
                                   __func__, rc);
                        goto out;
                }
@@ -670,7 +670,8 @@ static loff_t orangefs_file_llseek(struct file *file, loff_t offset, int origin)
                 * NOTE: We are only interested in file size here,
                 * so we set mask accordingly.
                 */
-               ret = orangefs_inode_getattr(inode, ORANGEFS_ATTR_SYS_SIZE, 0);
+               ret = orangefs_inode_old_getattr(inode,
+                   ORANGEFS_ATTR_SYS_SIZE, 0);
                if (ret) {
                        gossip_debug(GOSSIP_FILE_DEBUG,
                                     "%s:%s:%d calling make bad inode\n",
index a456252..fd591d4 100644 (file)
@@ -268,7 +268,8 @@ int orangefs_getattr(struct vfsmount *mnt,
                     "orangefs_getattr: called on %s\n",
                     dentry->d_name.name);
 
-       ret = orangefs_inode_getattr(inode, ORANGEFS_ATTR_SYS_ALL_NOHINT, 0);
+       ret = orangefs_inode_old_getattr(inode, ORANGEFS_ATTR_SYS_ALL_NOHINT,
+           0);
        if (ret == 0) {
                generic_fillattr(inode, kstat);
 
@@ -299,7 +300,7 @@ int orangefs_permission(struct inode *inode, int mask)
        gossip_debug(GOSSIP_INODE_DEBUG, "%s: refreshing\n", __func__);
 
        /* Make sure the permission (and other common attrs) are up to date. */
-       ret = orangefs_inode_getattr(inode,
+       ret = orangefs_inode_old_getattr(inode,
            ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE, 0);
        if (ret < 0)
                return ret;
@@ -401,7 +402,7 @@ struct inode *orangefs_iget(struct super_block *sb, struct orangefs_object_kref
        if (!inode || !(inode->i_state & I_NEW))
                return inode;
 
-       error = orangefs_inode_getattr(inode,
+       error = orangefs_inode_old_getattr(inode,
            ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE, 0);
        if (error) {
                iget_failed(inode);
@@ -447,7 +448,7 @@ struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
        orangefs_set_inode(inode, ref);
        inode->i_ino = hash;    /* needed for stat etc */
 
-       error = orangefs_inode_getattr(inode,
+       error = orangefs_inode_old_getattr(inode,
            ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE, 0);
        if (error)
                goto out_iput;
index 7846298..276685c 100644 (file)
@@ -544,7 +544,9 @@ int orangefs_inode_setxattr(struct inode *inode,
                         size_t size,
                         int flags);
 
-int orangefs_inode_getattr(struct inode *inode, __u32 mask, int check);
+int orangefs_inode_old_getattr(struct inode *inode, __u32 mask, int check);
+
+int orangefs_inode_getattr(struct inode *inode, int new, int size);
 
 int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr);
 
index df4ad04..59c51e2 100644 (file)
@@ -458,7 +458,8 @@ static int compare_attributes_to_inode(struct inode *inode,
  * otherwise. When check is 1, returns 1 on success where the inode is valid
  * and 0 on success where the inode is stale and -errno otherwise.
  */
-int orangefs_inode_getattr(struct inode *inode, __u32 getattr_mask, int check)
+int orangefs_inode_old_getattr(struct inode *inode, __u32 getattr_mask,
+    int check)
 {
        struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
        struct orangefs_kernel_op_s *new_op;
@@ -536,6 +537,124 @@ out:
        return ret;
 }
 
+static int orangefs_inode_type(enum orangefs_ds_type objtype)
+{
+       if (objtype == ORANGEFS_TYPE_METAFILE)
+               return S_IFREG;
+       else if (objtype == ORANGEFS_TYPE_DIRECTORY)
+               return S_IFDIR;
+       else if (objtype == ORANGEFS_TYPE_SYMLINK)
+               return S_IFLNK;
+       else
+               return -1;
+}
+
+int orangefs_inode_getattr(struct inode *inode, int new, int size)
+{
+       struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
+       struct orangefs_kernel_op_s *new_op;
+       loff_t inode_size, rounded_up_size;
+       int ret;
+
+       gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
+           get_khandle_from_ino(inode));
+
+       new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR);
+       if (!new_op)
+               return -ENOMEM;
+       new_op->upcall.req.getattr.refn = orangefs_inode->refn;
+       new_op->upcall.req.getattr.mask = size ?
+           ORANGEFS_ATTR_SYS_ALL_NOHINT : ORANGEFS_ATTR_SYS_ALL_NOHINT_NOSIZE;
+
+       ret = service_operation(new_op, __func__,
+           get_interruptible_flag(inode));
+       if (ret != 0)
+               goto out;
+
+       ret = orangefs_inode_type(new_op->
+           downcall.resp.getattr.attributes.objtype);
+       if (!new) {
+               /*
+                * If the inode type or symlink target have changed then this
+                * inode is stale.
+                */
+               if (ret == -1 || !(inode->i_mode & ret)) {
+                       orangefs_make_bad_inode(inode);
+                       ret = -ESTALE;
+                       goto out;
+               }
+               if (ret == S_IFLNK && strncmp(orangefs_inode->link_target,
+                   new_op->downcall.resp.getattr.link_target,
+                   ORANGEFS_NAME_MAX)) {
+                       orangefs_make_bad_inode(inode);
+                       ret = -ESTALE;
+                       goto out;
+               }
+       }
+
+       switch (ret) {
+       case S_IFREG:
+               inode->i_flags = orangefs_inode_flags(&new_op->
+                   downcall.resp.getattr.attributes);
+               if (size) {
+                       inode_size = (loff_t)new_op->
+                           downcall.resp.getattr.attributes.size;
+                       rounded_up_size =
+                           (inode_size + (4096 - (inode_size % 4096)));
+                       inode->i_size = inode_size;
+                       orangefs_inode->blksize =
+                           new_op->downcall.resp.getattr.attributes.blksize;
+                       spin_lock(&inode->i_lock);
+                       inode->i_bytes = inode_size;
+                       inode->i_blocks =
+                           (unsigned long)(rounded_up_size / 512);
+                       spin_unlock(&inode->i_lock);
+               }
+               break;
+       case S_IFDIR:
+               inode->i_size = PAGE_CACHE_SIZE;
+               orangefs_inode->blksize = (1 << inode->i_blkbits);
+               spin_lock(&inode->i_lock);
+               inode_set_bytes(inode, inode->i_size);
+               spin_unlock(&inode->i_lock);
+               set_nlink(inode, 1);
+               break;
+       case S_IFLNK:
+               if (new) {
+                       inode->i_size = (loff_t)strlen(new_op->
+                           downcall.resp.getattr.link_target);
+                       orangefs_inode->blksize = (1 << inode->i_blkbits);
+                       strlcpy(orangefs_inode->link_target,
+                           new_op->downcall.resp.getattr.link_target,
+                           ORANGEFS_NAME_MAX);
+               }
+               break;
+       }
+
+       inode->i_uid = make_kuid(&init_user_ns, new_op->
+           downcall.resp.getattr.attributes.owner);
+       inode->i_gid = make_kgid(&init_user_ns, new_op->
+           downcall.resp.getattr.attributes.group);
+       inode->i_atime.tv_sec = (time64_t)new_op->
+           downcall.resp.getattr.attributes.atime;
+       inode->i_mtime.tv_sec = (time64_t)new_op->
+           downcall.resp.getattr.attributes.mtime;
+       inode->i_ctime.tv_sec = (time64_t)new_op->
+           downcall.resp.getattr.attributes.ctime;
+       inode->i_atime.tv_nsec = 0;
+       inode->i_mtime.tv_nsec = 0;
+       inode->i_ctime.tv_nsec = 0;
+
+       /* special case: mark the root inode as sticky */
+       inode->i_mode = ret | (is_root_handle(inode) ? S_ISVTX : 0) |
+           orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
+
+       ret = 0;
+out:
+       op_release(new_op);
+       return ret;
+}
+
 /*
  * issues a orangefs setattr request to make sure the new attribute values
  * take effect if successful.  returns 0 on success; -errno otherwise