orangefs: use new getattr for revalidate and remove old getattr
authorMartin Brandenburg <martin@omnibond.com>
Thu, 17 Mar 2016 19:15:16 +0000 (15:15 -0400)
committerMike Marshall <hubcap@omnibond.com>
Wed, 23 Mar 2016 21:36:15 +0000 (17:36 -0400)
Signed-off-by: Martin Brandenburg <martin@omnibond.com>
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
fs/orangefs/dcache.c
fs/orangefs/orangefs-kernel.h
fs/orangefs/orangefs-utils.c

index cc5487a..5dfc4f3 100644 (file)
@@ -117,8 +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_old_getattr(dentry->d_inode,
-           ORANGEFS_ATTR_SYS_TYPE|ORANGEFS_ATTR_SYS_LNK_TARGET, 1);
+       ret = orangefs_inode_check_changed(dentry->d_inode);
        if (ret < 0) {
                gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n",
                    __FILE__, __func__, __LINE__);
index 276685c..5e85b19 100644 (file)
@@ -544,10 +544,10 @@ int orangefs_inode_setxattr(struct inode *inode,
                         size_t size,
                         int flags);
 
-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_check_changed(struct inode *inode);
+
 int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr);
 
 void orangefs_make_bad_inode(struct inode *inode);
index 59c51e2..6643a6a 100644 (file)
@@ -129,141 +129,6 @@ static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs)
        return perm_mode;
 }
 
-/* NOTE: symname is ignored unless the inode is a sym link */
-static int copy_attributes_to_inode(struct inode *inode,
-                                   struct ORANGEFS_sys_attr_s *attrs,
-                                   char *symname)
-{
-       int ret = -1;
-       struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
-       loff_t inode_size = 0;
-       loff_t rounded_up_size = 0;
-
-
-       /*
-        * arbitrarily set the inode block size; FIXME: we need to
-        * resolve the difference between the reported inode blocksize
-        * and the PAGE_CACHE_SIZE, since our block count will always
-        * be wrong.
-        *
-        * For now, we're setting the block count to be the proper
-        * number assuming the block size is 512 bytes, and the size is
-        * rounded up to the nearest 4K.  This is apparently required
-        * to get proper size reports from the 'du' shell utility.
-        *
-        * changing the inode->i_blkbits to something other than
-        * PAGE_CACHE_SHIFT breaks mmap/execution as we depend on that.
-        */
-       gossip_debug(GOSSIP_UTILS_DEBUG,
-                    "attrs->mask = %x (objtype = %s)\n",
-                    attrs->mask,
-                    attrs->objtype == ORANGEFS_TYPE_METAFILE ? "file" :
-                    attrs->objtype == ORANGEFS_TYPE_DIRECTORY ? "directory" :
-                    attrs->objtype == ORANGEFS_TYPE_SYMLINK ? "symlink" :
-                       "invalid/unknown");
-
-       switch (attrs->objtype) {
-       case ORANGEFS_TYPE_METAFILE:
-               inode->i_flags = orangefs_inode_flags(attrs);
-               if (attrs->mask & ORANGEFS_ATTR_SYS_SIZE) {
-                       inode_size = (loff_t) attrs->size;
-                       rounded_up_size =
-                           (inode_size + (4096 - (inode_size % 4096)));
-
-                       spin_lock(&inode->i_lock);
-                       inode->i_bytes = inode_size;
-                       inode->i_blocks =
-                           (unsigned long)(rounded_up_size / 512);
-                       spin_unlock(&inode->i_lock);
-
-                       /*
-                        * NOTE: make sure all the places we're called
-                        * from have the inode->i_sem lock. We're fine
-                        * in 99% of the cases since we're mostly
-                        * called from a lookup.
-                        */
-                       inode->i_size = inode_size;
-               }
-               break;
-       case ORANGEFS_TYPE_SYMLINK:
-               if (symname != NULL) {
-                       inode->i_size = (loff_t) strlen(symname);
-                       break;
-               }
-               /*FALLTHRU*/
-       default:
-               inode->i_size = PAGE_CACHE_SIZE;
-
-               spin_lock(&inode->i_lock);
-               inode_set_bytes(inode, inode->i_size);
-               spin_unlock(&inode->i_lock);
-               break;
-       }
-
-       inode->i_uid = make_kuid(&init_user_ns, attrs->owner);
-       inode->i_gid = make_kgid(&init_user_ns, attrs->group);
-       inode->i_atime.tv_sec = (time64_t) attrs->atime;
-       inode->i_mtime.tv_sec = (time64_t) attrs->mtime;
-       inode->i_ctime.tv_sec = (time64_t) attrs->ctime;
-       inode->i_atime.tv_nsec = 0;
-       inode->i_mtime.tv_nsec = 0;
-       inode->i_ctime.tv_nsec = 0;
-
-       inode->i_mode = orangefs_inode_perms(attrs);
-
-       if (is_root_handle(inode)) {
-               /* special case: mark the root inode as sticky */
-               inode->i_mode |= S_ISVTX;
-               gossip_debug(GOSSIP_UTILS_DEBUG,
-                            "Marking inode %pU as sticky\n",
-                            get_khandle_from_ino(inode));
-       }
-
-       switch (attrs->objtype) {
-       case ORANGEFS_TYPE_METAFILE:
-               inode->i_mode |= S_IFREG;
-               ret = 0;
-               break;
-       case ORANGEFS_TYPE_DIRECTORY:
-               inode->i_mode |= S_IFDIR;
-               /* NOTE: we have no good way to keep nlink consistent
-                * for directories across clients; keep constant at 1.
-                * Why 1?  If we go with 2, then find(1) gets confused
-                * and won't work properly withouth the -noleaf option
-                */
-               set_nlink(inode, 1);
-               ret = 0;
-               break;
-       case ORANGEFS_TYPE_SYMLINK:
-               inode->i_mode |= S_IFLNK;
-
-               /* copy link target to inode private data */
-               if (orangefs_inode && symname) {
-                       strncpy(orangefs_inode->link_target,
-                               symname,
-                               ORANGEFS_NAME_MAX);
-                       gossip_debug(GOSSIP_UTILS_DEBUG,
-                                    "Copied attr link target %s\n",
-                                    orangefs_inode->link_target);
-               }
-               gossip_debug(GOSSIP_UTILS_DEBUG,
-                            "symlink mode %o\n",
-                            inode->i_mode);
-               ret = 0;
-               break;
-       default:
-               gossip_err("orangefs: copy_attributes_to_inode: got invalid attribute type %x\n",
-                       attrs->objtype);
-       }
-
-       gossip_debug(GOSSIP_UTILS_DEBUG,
-                    "orangefs: copy_attributes_to_inode: setting i_mode to %o, i_size to %lu\n",
-                    inode->i_mode,
-                    (unsigned long)i_size_read(inode));
-
-       return ret;
-}
-
 /*
  * NOTE: in kernel land, we never use the sys_attr->link_target for
  * anything, so don't bother copying it into the sys_attr object here.
@@ -351,192 +216,6 @@ static inline int copy_attributes_from_inode(struct inode *inode,
        return 0;
 }
 
-static int compare_attributes_to_inode(struct inode *inode,
-                                      struct ORANGEFS_sys_attr_s *attrs,
-                                      char *symname,
-                                      int mask)
-{
-       struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
-       loff_t inode_size, rounded_up_size;
-
-       /* Much of what happens below relies on the type being around. */
-       if (!(mask & ORANGEFS_ATTR_SYS_TYPE))
-               return 0;
-
-       if (attrs->objtype == ORANGEFS_TYPE_METAFILE &&
-           inode->i_flags != orangefs_inode_flags(attrs))
-               return 0;
-
-       /* Compare file size. */
-
-       switch (attrs->objtype) {
-       case ORANGEFS_TYPE_METAFILE:
-               if (mask & ORANGEFS_ATTR_SYS_SIZE) {
-                       inode_size = attrs->size;
-                       rounded_up_size = inode_size +
-                           (4096 - (inode_size % 4096));
-                       if (inode->i_bytes != inode_size ||
-                           inode->i_blocks != rounded_up_size/512)
-                               return 0;
-               }
-               break;
-       case ORANGEFS_TYPE_SYMLINK:
-               if (mask & ORANGEFS_ATTR_SYS_SIZE)
-                       if (symname && strlen(symname) != inode->i_size)
-                               return 0;
-               break;
-       default:
-               if (inode->i_size != PAGE_CACHE_SIZE &&
-                   inode_get_bytes(inode) != PAGE_CACHE_SIZE)
-                       return 0;
-       }
-
-       /* Compare general attributes. */
-
-       if (mask & ORANGEFS_ATTR_SYS_UID &&
-           !uid_eq(inode->i_uid, make_kuid(&init_user_ns, attrs->owner)))
-               return 0;
-       if (mask & ORANGEFS_ATTR_SYS_GID &&
-           !gid_eq(inode->i_gid, make_kgid(&init_user_ns, attrs->group)))
-               return 0;
-       if (mask & ORANGEFS_ATTR_SYS_ATIME &&
-           inode->i_atime.tv_sec != attrs->atime)
-               return 0;
-       if (mask & ORANGEFS_ATTR_SYS_MTIME &&
-           inode->i_atime.tv_sec != attrs->mtime)
-               return 0;
-       if (mask & ORANGEFS_ATTR_SYS_CTIME &&
-           inode->i_atime.tv_sec != attrs->ctime)
-               return 0;
-       if (inode->i_atime.tv_nsec != 0 ||
-           inode->i_mtime.tv_nsec != 0 ||
-           inode->i_ctime.tv_nsec != 0)
-               return 0;
-
-       if (mask & ORANGEFS_ATTR_SYS_PERM &&
-           (inode->i_mode & ~(S_ISVTX|S_IFREG|S_IFDIR|S_IFLNK)) !=
-           orangefs_inode_perms(attrs))
-               return 0;
-
-       if (is_root_handle(inode))
-               if (!(inode->i_mode & S_ISVTX))
-                       return 0;
-
-       /* Compare file type. */
-
-       switch (attrs->objtype) {
-       case ORANGEFS_TYPE_METAFILE:
-               if (!S_ISREG(inode->i_mode))
-                       return 0;
-               break;
-       case ORANGEFS_TYPE_DIRECTORY:
-               if (!S_ISDIR(inode->i_mode))
-                       return 0;
-               if (inode->i_nlink != 1)
-                       return 0;
-               break;
-       case ORANGEFS_TYPE_SYMLINK:
-               if (!S_ISLNK(inode->i_mode))
-                       return 0;
-               if (orangefs_inode && symname &&
-                   mask & ORANGEFS_ATTR_SYS_LNK_TARGET)
-                       if (strcmp(orangefs_inode->link_target, symname))
-                               return 0;
-               break;
-       default:
-               gossip_err("orangefs: compare_attributes_to_inode: got invalid attribute type %x\n",
-                   attrs->objtype);
-
-       }
-
-       return 1;
-}
-
-/*
- * Issues a orangefs getattr request and fills in the appropriate inode
- * attributes if successful. When check is 0, returns 0 on success and -errno
- * 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_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;
-       int ret = -EINVAL;
-
-       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 = getattr_mask;
-
-       ret = service_operation(new_op, __func__,
-                               get_interruptible_flag(inode));
-       if (ret != 0)
-               goto out;
-
-       if (check) {
-               ret = compare_attributes_to_inode(inode,
-                   &new_op->downcall.resp.getattr.attributes,
-                   new_op->downcall.resp.getattr.link_target,
-                   getattr_mask);
-
-               if (new_op->downcall.resp.getattr.attributes.objtype ==
-                   ORANGEFS_TYPE_METAFILE) {
-                       if (orangefs_inode->blksize !=
-                           new_op->downcall.resp.getattr.attributes.blksize)
-                               ret = 0;
-               } else {
-                       if (orangefs_inode->blksize != 1 << inode->i_blkbits)
-                               ret = 0;
-               }
-       } else {
-               if (copy_attributes_to_inode(inode,
-                               &new_op->downcall.resp.getattr.attributes,
-                               new_op->downcall.resp.getattr.link_target)) {
-                       gossip_err("%s: failed to copy attributes\n", __func__);
-                       ret = -ENOENT;
-                       goto out;
-               }
-
-               /*
-                * Store blksize in orangefs specific part of inode structure;
-                * we are only going to use this to report to stat to make sure
-                * it doesn't perturb any inode related code paths.
-                */
-               if (new_op->downcall.resp.getattr.attributes.objtype ==
-                               ORANGEFS_TYPE_METAFILE) {
-                       orangefs_inode->blksize = new_op->downcall.resp.
-                           getattr.attributes.blksize;
-               } else {
-                       /*
-                        * mimic behavior of generic_fillattr() for other file
-                        * types.
-                        */
-                       orangefs_inode->blksize = (1 << inode->i_blkbits);
-
-               }
-       }
-
-out:
-       gossip_debug(GOSSIP_UTILS_DEBUG,
-                    "Getattr on handle %pU, "
-                    "fsid %d\n  (inode ct = %d) returned %d\n",
-                    &orangefs_inode->refn.khandle,
-                    orangefs_inode->refn.fs_id,
-                    (int)atomic_read(&inode->i_count),
-                    ret);
-
-       op_release(new_op);
-       return ret;
-}
-
 static int orangefs_inode_type(enum orangefs_ds_type objtype)
 {
        if (objtype == ORANGEFS_TYPE_METAFILE)
@@ -655,6 +334,52 @@ out:
        return ret;
 }
 
+int orangefs_inode_check_changed(struct inode *inode)
+{
+       struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
+       struct orangefs_kernel_op_s *new_op;
+       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 = ORANGEFS_ATTR_SYS_TYPE |
+           ORANGEFS_ATTR_SYS_LNK_TARGET;
+
+       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 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 = 1;
+               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 = 1;
+               goto out;
+       }
+
+       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