Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

orangefs: use new getattr for revalidate and remove old getattr

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
Signed-off-by: Mike Marshall <hubcap@omnibond.com>

authored by

Martin Brandenburg and committed by
Mike Marshall
5859d77e 8f24928d

+49 -325
+1 -2
fs/orangefs/dcache.c
··· 117 117 118 118 /* Now we must perform a getattr to validate the inode contents. */ 119 119 120 - ret = orangefs_inode_old_getattr(dentry->d_inode, 121 - ORANGEFS_ATTR_SYS_TYPE|ORANGEFS_ATTR_SYS_LNK_TARGET, 1); 120 + ret = orangefs_inode_check_changed(dentry->d_inode); 122 121 if (ret < 0) { 123 122 gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d getattr failure.\n", 124 123 __FILE__, __func__, __LINE__);
+2 -2
fs/orangefs/orangefs-kernel.h
··· 544 544 size_t size, 545 545 int flags); 546 546 547 - int orangefs_inode_old_getattr(struct inode *inode, __u32 mask, int check); 548 - 549 547 int orangefs_inode_getattr(struct inode *inode, int new, int size); 548 + 549 + int orangefs_inode_check_changed(struct inode *inode); 550 550 551 551 int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr); 552 552
+46 -321
fs/orangefs/orangefs-utils.c
··· 129 129 return perm_mode; 130 130 } 131 131 132 - /* NOTE: symname is ignored unless the inode is a sym link */ 133 - static int copy_attributes_to_inode(struct inode *inode, 134 - struct ORANGEFS_sys_attr_s *attrs, 135 - char *symname) 136 - { 137 - int ret = -1; 138 - struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 139 - loff_t inode_size = 0; 140 - loff_t rounded_up_size = 0; 141 - 142 - 143 - /* 144 - * arbitrarily set the inode block size; FIXME: we need to 145 - * resolve the difference between the reported inode blocksize 146 - * and the PAGE_CACHE_SIZE, since our block count will always 147 - * be wrong. 148 - * 149 - * For now, we're setting the block count to be the proper 150 - * number assuming the block size is 512 bytes, and the size is 151 - * rounded up to the nearest 4K. This is apparently required 152 - * to get proper size reports from the 'du' shell utility. 153 - * 154 - * changing the inode->i_blkbits to something other than 155 - * PAGE_CACHE_SHIFT breaks mmap/execution as we depend on that. 156 - */ 157 - gossip_debug(GOSSIP_UTILS_DEBUG, 158 - "attrs->mask = %x (objtype = %s)\n", 159 - attrs->mask, 160 - attrs->objtype == ORANGEFS_TYPE_METAFILE ? "file" : 161 - attrs->objtype == ORANGEFS_TYPE_DIRECTORY ? "directory" : 162 - attrs->objtype == ORANGEFS_TYPE_SYMLINK ? "symlink" : 163 - "invalid/unknown"); 164 - 165 - switch (attrs->objtype) { 166 - case ORANGEFS_TYPE_METAFILE: 167 - inode->i_flags = orangefs_inode_flags(attrs); 168 - if (attrs->mask & ORANGEFS_ATTR_SYS_SIZE) { 169 - inode_size = (loff_t) attrs->size; 170 - rounded_up_size = 171 - (inode_size + (4096 - (inode_size % 4096))); 172 - 173 - spin_lock(&inode->i_lock); 174 - inode->i_bytes = inode_size; 175 - inode->i_blocks = 176 - (unsigned long)(rounded_up_size / 512); 177 - spin_unlock(&inode->i_lock); 178 - 179 - /* 180 - * NOTE: make sure all the places we're called 181 - * from have the inode->i_sem lock. We're fine 182 - * in 99% of the cases since we're mostly 183 - * called from a lookup. 184 - */ 185 - inode->i_size = inode_size; 186 - } 187 - break; 188 - case ORANGEFS_TYPE_SYMLINK: 189 - if (symname != NULL) { 190 - inode->i_size = (loff_t) strlen(symname); 191 - break; 192 - } 193 - /*FALLTHRU*/ 194 - default: 195 - inode->i_size = PAGE_CACHE_SIZE; 196 - 197 - spin_lock(&inode->i_lock); 198 - inode_set_bytes(inode, inode->i_size); 199 - spin_unlock(&inode->i_lock); 200 - break; 201 - } 202 - 203 - inode->i_uid = make_kuid(&init_user_ns, attrs->owner); 204 - inode->i_gid = make_kgid(&init_user_ns, attrs->group); 205 - inode->i_atime.tv_sec = (time64_t) attrs->atime; 206 - inode->i_mtime.tv_sec = (time64_t) attrs->mtime; 207 - inode->i_ctime.tv_sec = (time64_t) attrs->ctime; 208 - inode->i_atime.tv_nsec = 0; 209 - inode->i_mtime.tv_nsec = 0; 210 - inode->i_ctime.tv_nsec = 0; 211 - 212 - inode->i_mode = orangefs_inode_perms(attrs); 213 - 214 - if (is_root_handle(inode)) { 215 - /* special case: mark the root inode as sticky */ 216 - inode->i_mode |= S_ISVTX; 217 - gossip_debug(GOSSIP_UTILS_DEBUG, 218 - "Marking inode %pU as sticky\n", 219 - get_khandle_from_ino(inode)); 220 - } 221 - 222 - switch (attrs->objtype) { 223 - case ORANGEFS_TYPE_METAFILE: 224 - inode->i_mode |= S_IFREG; 225 - ret = 0; 226 - break; 227 - case ORANGEFS_TYPE_DIRECTORY: 228 - inode->i_mode |= S_IFDIR; 229 - /* NOTE: we have no good way to keep nlink consistent 230 - * for directories across clients; keep constant at 1. 231 - * Why 1? If we go with 2, then find(1) gets confused 232 - * and won't work properly withouth the -noleaf option 233 - */ 234 - set_nlink(inode, 1); 235 - ret = 0; 236 - break; 237 - case ORANGEFS_TYPE_SYMLINK: 238 - inode->i_mode |= S_IFLNK; 239 - 240 - /* copy link target to inode private data */ 241 - if (orangefs_inode && symname) { 242 - strncpy(orangefs_inode->link_target, 243 - symname, 244 - ORANGEFS_NAME_MAX); 245 - gossip_debug(GOSSIP_UTILS_DEBUG, 246 - "Copied attr link target %s\n", 247 - orangefs_inode->link_target); 248 - } 249 - gossip_debug(GOSSIP_UTILS_DEBUG, 250 - "symlink mode %o\n", 251 - inode->i_mode); 252 - ret = 0; 253 - break; 254 - default: 255 - gossip_err("orangefs: copy_attributes_to_inode: got invalid attribute type %x\n", 256 - attrs->objtype); 257 - } 258 - 259 - gossip_debug(GOSSIP_UTILS_DEBUG, 260 - "orangefs: copy_attributes_to_inode: setting i_mode to %o, i_size to %lu\n", 261 - inode->i_mode, 262 - (unsigned long)i_size_read(inode)); 263 - 264 - return ret; 265 - } 266 - 267 132 /* 268 133 * NOTE: in kernel land, we never use the sys_attr->link_target for 269 134 * anything, so don't bother copying it into the sys_attr object here. ··· 214 349 } 215 350 216 351 return 0; 217 - } 218 - 219 - static int compare_attributes_to_inode(struct inode *inode, 220 - struct ORANGEFS_sys_attr_s *attrs, 221 - char *symname, 222 - int mask) 223 - { 224 - struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 225 - loff_t inode_size, rounded_up_size; 226 - 227 - /* Much of what happens below relies on the type being around. */ 228 - if (!(mask & ORANGEFS_ATTR_SYS_TYPE)) 229 - return 0; 230 - 231 - if (attrs->objtype == ORANGEFS_TYPE_METAFILE && 232 - inode->i_flags != orangefs_inode_flags(attrs)) 233 - return 0; 234 - 235 - /* Compare file size. */ 236 - 237 - switch (attrs->objtype) { 238 - case ORANGEFS_TYPE_METAFILE: 239 - if (mask & ORANGEFS_ATTR_SYS_SIZE) { 240 - inode_size = attrs->size; 241 - rounded_up_size = inode_size + 242 - (4096 - (inode_size % 4096)); 243 - if (inode->i_bytes != inode_size || 244 - inode->i_blocks != rounded_up_size/512) 245 - return 0; 246 - } 247 - break; 248 - case ORANGEFS_TYPE_SYMLINK: 249 - if (mask & ORANGEFS_ATTR_SYS_SIZE) 250 - if (symname && strlen(symname) != inode->i_size) 251 - return 0; 252 - break; 253 - default: 254 - if (inode->i_size != PAGE_CACHE_SIZE && 255 - inode_get_bytes(inode) != PAGE_CACHE_SIZE) 256 - return 0; 257 - } 258 - 259 - /* Compare general attributes. */ 260 - 261 - if (mask & ORANGEFS_ATTR_SYS_UID && 262 - !uid_eq(inode->i_uid, make_kuid(&init_user_ns, attrs->owner))) 263 - return 0; 264 - if (mask & ORANGEFS_ATTR_SYS_GID && 265 - !gid_eq(inode->i_gid, make_kgid(&init_user_ns, attrs->group))) 266 - return 0; 267 - if (mask & ORANGEFS_ATTR_SYS_ATIME && 268 - inode->i_atime.tv_sec != attrs->atime) 269 - return 0; 270 - if (mask & ORANGEFS_ATTR_SYS_MTIME && 271 - inode->i_atime.tv_sec != attrs->mtime) 272 - return 0; 273 - if (mask & ORANGEFS_ATTR_SYS_CTIME && 274 - inode->i_atime.tv_sec != attrs->ctime) 275 - return 0; 276 - if (inode->i_atime.tv_nsec != 0 || 277 - inode->i_mtime.tv_nsec != 0 || 278 - inode->i_ctime.tv_nsec != 0) 279 - return 0; 280 - 281 - if (mask & ORANGEFS_ATTR_SYS_PERM && 282 - (inode->i_mode & ~(S_ISVTX|S_IFREG|S_IFDIR|S_IFLNK)) != 283 - orangefs_inode_perms(attrs)) 284 - return 0; 285 - 286 - if (is_root_handle(inode)) 287 - if (!(inode->i_mode & S_ISVTX)) 288 - return 0; 289 - 290 - /* Compare file type. */ 291 - 292 - switch (attrs->objtype) { 293 - case ORANGEFS_TYPE_METAFILE: 294 - if (!S_ISREG(inode->i_mode)) 295 - return 0; 296 - break; 297 - case ORANGEFS_TYPE_DIRECTORY: 298 - if (!S_ISDIR(inode->i_mode)) 299 - return 0; 300 - if (inode->i_nlink != 1) 301 - return 0; 302 - break; 303 - case ORANGEFS_TYPE_SYMLINK: 304 - if (!S_ISLNK(inode->i_mode)) 305 - return 0; 306 - if (orangefs_inode && symname && 307 - mask & ORANGEFS_ATTR_SYS_LNK_TARGET) 308 - if (strcmp(orangefs_inode->link_target, symname)) 309 - return 0; 310 - break; 311 - default: 312 - gossip_err("orangefs: compare_attributes_to_inode: got invalid attribute type %x\n", 313 - attrs->objtype); 314 - 315 - } 316 - 317 - return 1; 318 - } 319 - 320 - /* 321 - * Issues a orangefs getattr request and fills in the appropriate inode 322 - * attributes if successful. When check is 0, returns 0 on success and -errno 323 - * otherwise. When check is 1, returns 1 on success where the inode is valid 324 - * and 0 on success where the inode is stale and -errno otherwise. 325 - */ 326 - int orangefs_inode_old_getattr(struct inode *inode, __u32 getattr_mask, 327 - int check) 328 - { 329 - struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 330 - struct orangefs_kernel_op_s *new_op; 331 - int ret = -EINVAL; 332 - 333 - gossip_debug(GOSSIP_UTILS_DEBUG, 334 - "%s: called on inode %pU\n", 335 - __func__, 336 - get_khandle_from_ino(inode)); 337 - 338 - new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR); 339 - if (!new_op) 340 - return -ENOMEM; 341 - new_op->upcall.req.getattr.refn = orangefs_inode->refn; 342 - new_op->upcall.req.getattr.mask = getattr_mask; 343 - 344 - ret = service_operation(new_op, __func__, 345 - get_interruptible_flag(inode)); 346 - if (ret != 0) 347 - goto out; 348 - 349 - if (check) { 350 - ret = compare_attributes_to_inode(inode, 351 - &new_op->downcall.resp.getattr.attributes, 352 - new_op->downcall.resp.getattr.link_target, 353 - getattr_mask); 354 - 355 - if (new_op->downcall.resp.getattr.attributes.objtype == 356 - ORANGEFS_TYPE_METAFILE) { 357 - if (orangefs_inode->blksize != 358 - new_op->downcall.resp.getattr.attributes.blksize) 359 - ret = 0; 360 - } else { 361 - if (orangefs_inode->blksize != 1 << inode->i_blkbits) 362 - ret = 0; 363 - } 364 - } else { 365 - if (copy_attributes_to_inode(inode, 366 - &new_op->downcall.resp.getattr.attributes, 367 - new_op->downcall.resp.getattr.link_target)) { 368 - gossip_err("%s: failed to copy attributes\n", __func__); 369 - ret = -ENOENT; 370 - goto out; 371 - } 372 - 373 - /* 374 - * Store blksize in orangefs specific part of inode structure; 375 - * we are only going to use this to report to stat to make sure 376 - * it doesn't perturb any inode related code paths. 377 - */ 378 - if (new_op->downcall.resp.getattr.attributes.objtype == 379 - ORANGEFS_TYPE_METAFILE) { 380 - orangefs_inode->blksize = new_op->downcall.resp. 381 - getattr.attributes.blksize; 382 - } else { 383 - /* 384 - * mimic behavior of generic_fillattr() for other file 385 - * types. 386 - */ 387 - orangefs_inode->blksize = (1 << inode->i_blkbits); 388 - 389 - } 390 - } 391 - 392 - out: 393 - gossip_debug(GOSSIP_UTILS_DEBUG, 394 - "Getattr on handle %pU, " 395 - "fsid %d\n (inode ct = %d) returned %d\n", 396 - &orangefs_inode->refn.khandle, 397 - orangefs_inode->refn.fs_id, 398 - (int)atomic_read(&inode->i_count), 399 - ret); 400 - 401 - op_release(new_op); 402 - return ret; 403 352 } 404 353 405 354 static int orangefs_inode_type(enum orangefs_ds_type objtype) ··· 327 648 /* special case: mark the root inode as sticky */ 328 649 inode->i_mode = ret | (is_root_handle(inode) ? S_ISVTX : 0) | 329 650 orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes); 651 + 652 + ret = 0; 653 + out: 654 + op_release(new_op); 655 + return ret; 656 + } 657 + 658 + int orangefs_inode_check_changed(struct inode *inode) 659 + { 660 + struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 661 + struct orangefs_kernel_op_s *new_op; 662 + int ret; 663 + 664 + gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__, 665 + get_khandle_from_ino(inode)); 666 + 667 + new_op = op_alloc(ORANGEFS_VFS_OP_GETATTR); 668 + if (!new_op) 669 + return -ENOMEM; 670 + new_op->upcall.req.getattr.refn = orangefs_inode->refn; 671 + new_op->upcall.req.getattr.mask = ORANGEFS_ATTR_SYS_TYPE | 672 + ORANGEFS_ATTR_SYS_LNK_TARGET; 673 + 674 + ret = service_operation(new_op, __func__, 675 + get_interruptible_flag(inode)); 676 + if (ret != 0) 677 + goto out; 678 + 679 + ret = orangefs_inode_type(new_op-> 680 + downcall.resp.getattr.attributes.objtype); 681 + /* 682 + * If the inode type or symlink target have changed then this 683 + * inode is stale. 684 + */ 685 + if (ret == -1 || !(inode->i_mode & ret)) { 686 + orangefs_make_bad_inode(inode); 687 + ret = 1; 688 + goto out; 689 + } 690 + if (ret == S_IFLNK && strncmp(orangefs_inode->link_target, 691 + new_op->downcall.resp.getattr.link_target, 692 + ORANGEFS_NAME_MAX)) { 693 + orangefs_make_bad_inode(inode); 694 + ret = 1; 695 + goto out; 696 + } 330 697 331 698 ret = 0; 332 699 out: