Loading fs/orangefs/dcache.c +1 −2 Original line number Original line Diff line number Diff line Loading @@ -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. */ /* Now we must perform a getattr to validate the inode contents. */ ret = orangefs_inode_old_getattr(dentry->d_inode, ret = orangefs_inode_check_changed(dentry->d_inode); ORANGEFS_ATTR_SYS_TYPE|ORANGEFS_ATTR_SYS_LNK_TARGET, 1); if (ret < 0) { if (ret < 0) { gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n", gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n", __FILE__, __func__, __LINE__); __FILE__, __func__, __LINE__); Loading fs/orangefs/orangefs-kernel.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -544,10 +544,10 @@ int orangefs_inode_setxattr(struct inode *inode, size_t size, size_t size, int flags); 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_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); int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr); void orangefs_make_bad_inode(struct inode *inode); void orangefs_make_bad_inode(struct inode *inode); Loading fs/orangefs/orangefs-utils.c +46 −321 Original line number Original line Diff line number Diff line Loading @@ -129,141 +129,6 @@ static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs) return perm_mode; 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 * 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. * anything, so don't bother copying it into the sys_attr object here. Loading Loading @@ -351,192 +216,6 @@ static inline int copy_attributes_from_inode(struct inode *inode, return 0; 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) static int orangefs_inode_type(enum orangefs_ds_type objtype) { { if (objtype == ORANGEFS_TYPE_METAFILE) if (objtype == ORANGEFS_TYPE_METAFILE) Loading Loading @@ -655,6 +334,52 @@ int orangefs_inode_getattr(struct inode *inode, int new, int size) return ret; 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 * issues a orangefs setattr request to make sure the new attribute values * take effect if successful. returns 0 on success; -errno otherwise * take effect if successful. returns 0 on success; -errno otherwise Loading Loading
fs/orangefs/dcache.c +1 −2 Original line number Original line Diff line number Diff line Loading @@ -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. */ /* Now we must perform a getattr to validate the inode contents. */ ret = orangefs_inode_old_getattr(dentry->d_inode, ret = orangefs_inode_check_changed(dentry->d_inode); ORANGEFS_ATTR_SYS_TYPE|ORANGEFS_ATTR_SYS_LNK_TARGET, 1); if (ret < 0) { if (ret < 0) { gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n", gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n", __FILE__, __func__, __LINE__); __FILE__, __func__, __LINE__); Loading
fs/orangefs/orangefs-kernel.h +2 −2 Original line number Original line Diff line number Diff line Loading @@ -544,10 +544,10 @@ int orangefs_inode_setxattr(struct inode *inode, size_t size, size_t size, int flags); 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_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); int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr); void orangefs_make_bad_inode(struct inode *inode); void orangefs_make_bad_inode(struct inode *inode); Loading
fs/orangefs/orangefs-utils.c +46 −321 Original line number Original line Diff line number Diff line Loading @@ -129,141 +129,6 @@ static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs) return perm_mode; 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 * 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. * anything, so don't bother copying it into the sys_attr object here. Loading Loading @@ -351,192 +216,6 @@ static inline int copy_attributes_from_inode(struct inode *inode, return 0; 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) static int orangefs_inode_type(enum orangefs_ds_type objtype) { { if (objtype == ORANGEFS_TYPE_METAFILE) if (objtype == ORANGEFS_TYPE_METAFILE) Loading Loading @@ -655,6 +334,52 @@ int orangefs_inode_getattr(struct inode *inode, int new, int size) return ret; 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 * issues a orangefs setattr request to make sure the new attribute values * take effect if successful. returns 0 on success; -errno otherwise * take effect if successful. returns 0 on success; -errno otherwise Loading