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

orangefs: stop setting atime on inode dirty

The previous code path was to mark the inode dirty, let
orangefs_inode_dirty set a flag in our private inode, then later during
inode release call orangefs_flush_inode which notices the flag and
writes the atime out.

The code path worked almost identically for mtime, ctime, and mode
except that those flags are set explicitly and not as side effects of
dirty.

Now orangefs_flush_inode is removed. Marking an inode dirty does not
imply an atime update. Any place where flags were set before is now
an explicit call to orangefs_inode_setattr. Since OrangeFS does not
utilize inode writeback, the attribute change should be written out
immediately.

Fixes generic/120.

In namei.c, there are several places where the directory mtime and ctime
are set, but only the mtime is sent to the server. These don't seem
right, but I've left them as is for now.

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
a55f2d86 296200d3

+52 -141
+5 -5
fs/orangefs/acl.c
··· 155 155 156 156 int orangefs_init_acl(struct inode *inode, struct inode *dir) 157 157 { 158 - struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 159 158 struct posix_acl *default_acl, *acl; 160 159 umode_t mode = inode->i_mode; 160 + struct iattr iattr; 161 161 int error = 0; 162 - 163 - ClearModeFlag(orangefs_inode); 164 162 165 163 error = posix_acl_create(dir, &mode, &default_acl, &acl); 166 164 if (error) ··· 178 180 179 181 /* If mode of the inode was changed, then do a forcible ->setattr */ 180 182 if (mode != inode->i_mode) { 181 - SetModeFlag(orangefs_inode); 183 + memset(&iattr, 0, sizeof iattr); 182 184 inode->i_mode = mode; 183 - orangefs_flush_inode(inode); 185 + iattr.ia_mode = mode; 186 + iattr.ia_valid |= ATTR_MODE; 187 + orangefs_inode_setattr(inode, &iattr); 184 188 } 185 189 186 190 return error;
-1
fs/orangefs/dir.c
··· 386 386 { 387 387 struct orangefs_dir *od = file->private_data; 388 388 struct orangefs_dir_part *part = od->part; 389 - orangefs_flush_inode(inode); 390 389 while (part) { 391 390 struct orangefs_dir_part *next = part->next; 392 391 vfree(part);
+9 -7
fs/orangefs/file.c
··· 383 383 if (type == ORANGEFS_IO_READ) { 384 384 file_accessed(file); 385 385 } else { 386 - SetMtimeFlag(orangefs_inode); 387 - inode->i_mtime = current_time(inode); 388 - mark_inode_dirty_sync(inode); 386 + file_update_time(file); 387 + /* 388 + * Must invalidate to ensure write loop doesn't 389 + * prevent kernel from reading updated 390 + * attribute. Size probably changed because of 391 + * the write, and other clients could update 392 + * any other attribute. 393 + */ 394 + orangefs_inode->getattr_time = jiffies - 1; 389 395 } 390 396 } 391 397 ··· 621 615 "orangefs_file_release: called on %pD\n", 622 616 file); 623 617 624 - orangefs_flush_inode(inode); 625 - 626 618 /* 627 619 * remove all associated inode pages from the page cache and 628 620 * readahead cache (if any); this forces an expensive refresh of ··· 670 666 ret); 671 667 672 668 op_release(new_op); 673 - 674 - orangefs_flush_inode(file_inode(file)); 675 669 return ret; 676 670 } 677 671
+17
fs/orangefs/inode.c
··· 290 290 return generic_permission(inode, mask); 291 291 } 292 292 293 + int orangefs_update_time(struct inode *inode, struct timespec *time, int flags) 294 + { 295 + struct iattr iattr; 296 + gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_update_time: %pU\n", 297 + get_khandle_from_ino(inode)); 298 + generic_update_time(inode, time, flags); 299 + memset(&iattr, 0, sizeof iattr); 300 + if (flags & S_ATIME) 301 + iattr.ia_valid |= ATTR_ATIME; 302 + if (flags & S_CTIME) 303 + iattr.ia_valid |= ATTR_CTIME; 304 + if (flags & S_MTIME) 305 + iattr.ia_valid |= ATTR_MTIME; 306 + return orangefs_inode_setattr(inode, &iattr); 307 + } 308 + 293 309 /* ORANGEDS2 implementation of VFS inode operations for files */ 294 310 const struct inode_operations orangefs_file_inode_operations = { 295 311 .get_acl = orangefs_get_acl, ··· 314 298 .getattr = orangefs_getattr, 315 299 .listxattr = orangefs_listxattr, 316 300 .permission = orangefs_permission, 301 + .update_time = orangefs_update_time, 317 302 }; 318 303 319 304 static int orangefs_init_iops(struct inode *inode)
+17 -4
fs/orangefs/namei.c
··· 23 23 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 24 24 struct orangefs_kernel_op_s *new_op; 25 25 struct inode *inode; 26 + struct iattr iattr; 26 27 int ret; 27 28 28 29 gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n", ··· 83 82 __func__, 84 83 dentry); 85 84 86 - SetMtimeFlag(parent); 87 85 dir->i_mtime = dir->i_ctime = current_time(dir); 86 + memset(&iattr, 0, sizeof iattr); 87 + iattr.ia_valid |= ATTR_MTIME; 88 + orangefs_inode_setattr(dir, &iattr); 88 89 mark_inode_dirty_sync(dir); 89 90 ret = 0; 90 91 out: ··· 224 221 struct inode *inode = dentry->d_inode; 225 222 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 226 223 struct orangefs_kernel_op_s *new_op; 224 + struct iattr iattr; 227 225 int ret; 228 226 229 227 gossip_debug(GOSSIP_NAME_DEBUG, ··· 257 253 if (!ret) { 258 254 drop_nlink(inode); 259 255 260 - SetMtimeFlag(parent); 261 256 dir->i_mtime = dir->i_ctime = current_time(dir); 257 + memset(&iattr, 0, sizeof iattr); 258 + iattr.ia_valid |= ATTR_MTIME; 259 + orangefs_inode_setattr(dir, &iattr); 262 260 mark_inode_dirty_sync(dir); 263 261 } 264 262 return ret; ··· 273 267 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 274 268 struct orangefs_kernel_op_s *new_op; 275 269 struct inode *inode; 270 + struct iattr iattr; 276 271 int mode = 755; 277 272 int ret; 278 273 ··· 338 331 get_khandle_from_ino(inode), 339 332 dentry); 340 333 341 - SetMtimeFlag(parent); 342 334 dir->i_mtime = dir->i_ctime = current_time(dir); 335 + memset(&iattr, 0, sizeof iattr); 336 + iattr.ia_valid |= ATTR_MTIME; 337 + orangefs_inode_setattr(dir, &iattr); 343 338 mark_inode_dirty_sync(dir); 344 339 ret = 0; 345 340 out: ··· 354 345 struct orangefs_inode_s *parent = ORANGEFS_I(dir); 355 346 struct orangefs_kernel_op_s *new_op; 356 347 struct inode *inode; 348 + struct iattr iattr; 357 349 int ret; 358 350 359 351 new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR); ··· 410 400 * NOTE: we have no good way to keep nlink consistent for directories 411 401 * across clients; keep constant at 1. 412 402 */ 413 - SetMtimeFlag(parent); 414 403 dir->i_mtime = dir->i_ctime = current_time(dir); 404 + memset(&iattr, 0, sizeof iattr); 405 + iattr.ia_valid |= ATTR_MTIME; 406 + orangefs_inode_setattr(dir, &iattr); 415 407 mark_inode_dirty_sync(dir); 416 408 out: 417 409 op_release(new_op); ··· 482 470 .getattr = orangefs_getattr, 483 471 .listxattr = orangefs_listxattr, 484 472 .permission = orangefs_permission, 473 + .update_time = orangefs_update_time, 485 474 };
+2 -29
fs/orangefs/orangefs-kernel.h
··· 209 209 struct inode vfs_inode; 210 210 sector_t last_failed_block_index_read; 211 211 212 - /* 213 - * State of in-memory attributes not yet flushed to disk associated 214 - * with this object 215 - */ 216 - unsigned long pinode_flags; 217 - 218 212 unsigned long getattr_time; 219 213 u32 getattr_mask; 220 214 }; 221 - 222 - #define P_ATIME_FLAG 0 223 - #define P_MTIME_FLAG 1 224 - #define P_CTIME_FLAG 2 225 - #define P_MODE_FLAG 3 226 - 227 - #define ClearAtimeFlag(pinode) clear_bit(P_ATIME_FLAG, &(pinode)->pinode_flags) 228 - #define SetAtimeFlag(pinode) set_bit(P_ATIME_FLAG, &(pinode)->pinode_flags) 229 - #define AtimeFlag(pinode) test_bit(P_ATIME_FLAG, &(pinode)->pinode_flags) 230 - 231 - #define ClearMtimeFlag(pinode) clear_bit(P_MTIME_FLAG, &(pinode)->pinode_flags) 232 - #define SetMtimeFlag(pinode) set_bit(P_MTIME_FLAG, &(pinode)->pinode_flags) 233 - #define MtimeFlag(pinode) test_bit(P_MTIME_FLAG, &(pinode)->pinode_flags) 234 - 235 - #define ClearCtimeFlag(pinode) clear_bit(P_CTIME_FLAG, &(pinode)->pinode_flags) 236 - #define SetCtimeFlag(pinode) set_bit(P_CTIME_FLAG, &(pinode)->pinode_flags) 237 - #define CtimeFlag(pinode) test_bit(P_CTIME_FLAG, &(pinode)->pinode_flags) 238 - 239 - #define ClearModeFlag(pinode) clear_bit(P_MODE_FLAG, &(pinode)->pinode_flags) 240 - #define SetModeFlag(pinode) set_bit(P_MODE_FLAG, &(pinode)->pinode_flags) 241 - #define ModeFlag(pinode) test_bit(P_MODE_FLAG, &(pinode)->pinode_flags) 242 215 243 216 /* per superblock private orangefs info */ 244 217 struct orangefs_sb_info_s { ··· 415 442 416 443 int orangefs_permission(struct inode *inode, int mask); 417 444 445 + int orangefs_update_time(struct inode *, struct timespec *, int); 446 + 418 447 /* 419 448 * defined in xattr.c 420 449 */ ··· 458 483 * defined in orangefs-utils.c 459 484 */ 460 485 __s32 fsid_of_op(struct orangefs_kernel_op_s *op); 461 - 462 - int orangefs_flush_inode(struct inode *inode); 463 486 464 487 ssize_t orangefs_inode_getxattr(struct inode *inode, 465 488 const char *name,
+1 -82
fs/orangefs/orangefs-utils.c
··· 438 438 439 439 op_release(new_op); 440 440 441 - /* 442 - * successful setattr should clear the atime, mtime and 443 - * ctime flags. 444 - */ 445 - if (ret == 0) { 446 - ClearAtimeFlag(orangefs_inode); 447 - ClearMtimeFlag(orangefs_inode); 448 - ClearCtimeFlag(orangefs_inode); 449 - ClearModeFlag(orangefs_inode); 441 + if (ret == 0) 450 442 orangefs_inode->getattr_time = jiffies - 1; 451 - } 452 - 453 - return ret; 454 - } 455 - 456 - int orangefs_flush_inode(struct inode *inode) 457 - { 458 - /* 459 - * If it is a dirty inode, this function gets called. 460 - * Gather all the information that needs to be setattr'ed 461 - * Right now, this will only be used for mode, atime, mtime 462 - * and/or ctime. 463 - */ 464 - struct iattr wbattr; 465 - int ret; 466 - int mtime_flag; 467 - int ctime_flag; 468 - int atime_flag; 469 - int mode_flag; 470 - struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 471 - 472 - memset(&wbattr, 0, sizeof(wbattr)); 473 - 474 - /* 475 - * check inode flags up front, and clear them if they are set. This 476 - * will prevent multiple processes from all trying to flush the same 477 - * inode if they call close() simultaneously 478 - */ 479 - mtime_flag = MtimeFlag(orangefs_inode); 480 - ClearMtimeFlag(orangefs_inode); 481 - ctime_flag = CtimeFlag(orangefs_inode); 482 - ClearCtimeFlag(orangefs_inode); 483 - atime_flag = AtimeFlag(orangefs_inode); 484 - ClearAtimeFlag(orangefs_inode); 485 - mode_flag = ModeFlag(orangefs_inode); 486 - ClearModeFlag(orangefs_inode); 487 - 488 - /* -- Lazy atime,mtime and ctime update -- 489 - * Note: all times are dictated by server in the new scheme 490 - * and not by the clients 491 - * 492 - * Also mode updates are being handled now.. 493 - */ 494 - 495 - if (mtime_flag) 496 - wbattr.ia_valid |= ATTR_MTIME; 497 - if (ctime_flag) 498 - wbattr.ia_valid |= ATTR_CTIME; 499 - if (atime_flag) 500 - wbattr.ia_valid |= ATTR_ATIME; 501 - 502 - if (mode_flag) { 503 - wbattr.ia_mode = inode->i_mode; 504 - wbattr.ia_valid |= ATTR_MODE; 505 - } 506 - 507 - gossip_debug(GOSSIP_UTILS_DEBUG, 508 - "*********** orangefs_flush_inode: %pU " 509 - "(ia_valid %d)\n", 510 - get_khandle_from_ino(inode), 511 - wbattr.ia_valid); 512 - if (wbattr.ia_valid == 0) { 513 - gossip_debug(GOSSIP_UTILS_DEBUG, 514 - "orangefs_flush_inode skipping setattr()\n"); 515 - return 0; 516 - } 517 - 518 - gossip_debug(GOSSIP_UTILS_DEBUG, 519 - "orangefs_flush_inode (%pU) writing mode %o\n", 520 - get_khandle_from_ino(inode), 521 - inode->i_mode); 522 - 523 - ret = orangefs_inode_setattr(inode, &wbattr); 524 443 525 444 return ret; 526 445 }
-13
fs/orangefs/super.c
··· 117 117 orangefs_inode->refn.fs_id = ORANGEFS_FS_ID_NULL; 118 118 orangefs_inode->last_failed_block_index_read = 0; 119 119 memset(orangefs_inode->link_target, 0, sizeof(orangefs_inode->link_target)); 120 - orangefs_inode->pinode_flags = 0; 121 120 122 121 gossip_debug(GOSSIP_SUPER_DEBUG, 123 122 "orangefs_alloc_inode: allocated %p\n", ··· 296 297 { 297 298 } 298 299 299 - /* Called whenever the VFS dirties the inode in response to atime updates */ 300 - static void orangefs_dirty_inode(struct inode *inode, int flags) 301 - { 302 - struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); 303 - 304 - gossip_debug(GOSSIP_SUPER_DEBUG, 305 - "orangefs_dirty_inode: %pU\n", 306 - get_khandle_from_ino(inode)); 307 - SetAtimeFlag(orangefs_inode); 308 - } 309 - 310 300 static const struct super_operations orangefs_s_ops = { 311 301 .alloc_inode = orangefs_alloc_inode, 312 302 .destroy_inode = orangefs_destroy_inode, 313 - .dirty_inode = orangefs_dirty_inode, 314 303 .drop_inode = generic_delete_inode, 315 304 .statfs = orangefs_statfs, 316 305 .remount_fs = orangefs_remount_fs,
+1
fs/orangefs/symlink.c
··· 15 15 .getattr = orangefs_getattr, 16 16 .listxattr = orangefs_listxattr, 17 17 .permission = orangefs_permission, 18 + .update_time = orangefs_update_time, 18 19 };