1. 29 10月, 2020 2 次提交
  2. 28 10月, 2020 4 次提交
  3. 16 10月, 2020 6 次提交
    • D
      afs: Don't assert on unpurgeable server records · 7530d3eb
      David Howells 提交于
      Don't give an assertion failure on unpurgeable afs_server records - which
      kills the thread - but rather emit a trace line when we are purging a
      record (which only happens during network namespace removal or rmmod) and
      print a notice of the problem.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      7530d3eb
    • D
      afs: Add tracing for cell refcount and active user count · dca54a7b
      David Howells 提交于
      Add a tracepoint to log the cell refcount and active user count and pass in
      a reason code through various functions that manipulate these counters.
      
      Additionally, a helper function, afs_see_cell(), is provided to log
      interesting places that deal with a cell without actually doing any
      accounting directly.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      dca54a7b
    • D
      afs: Fix cell removal · 1d0e850a
      David Howells 提交于
      Fix cell removal by inserting a more final state than AFS_CELL_FAILED that
      indicates that the cell has been unpublished in case the manager is already
      requeued and will go through again.  The new AFS_CELL_REMOVED state will
      just immediately leave the manager function.
      
      Going through a second time in the AFS_CELL_FAILED state will cause it to
      try to remove the cell again, potentially leading to the proc list being
      removed.
      
      Fixes: 989782dc ("afs: Overhaul cell database management")
      Reported-by: syzbot+b994ecf2b023f14832c1@syzkaller.appspotmail.com
      Reported-by: syzbot+0e0db88e1eb44a91ae8d@syzkaller.appspotmail.com
      Reported-by: syzbot+2d0585e5efcd43d113c2@syzkaller.appspotmail.com
      Reported-by: syzbot+1ecc2f9d3387f1d79d42@syzkaller.appspotmail.com
      Reported-by: syzbot+18d51774588492bf3f69@syzkaller.appspotmail.com
      Reported-by: syzbot+a5e4946b04d6ca8fa5f3@syzkaller.appspotmail.com
      Suggested-by: NHillf Danton <hdanton@sina.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      cc: Hillf Danton <hdanton@sina.com>
      1d0e850a
    • D
      afs: Fix cell purging with aliases · 286377f6
      David Howells 提交于
      When the afs module is removed, one of the things that has to be done is to
      purge the cell database.  afs_cell_purge() cancels the management timer and
      then starts the cell manager work item to do the purging.  This does a
      single run through and then assumes that all cells are now purged - but
      this is no longer the case.
      
      With the introduction of alias detection, a later cell in the database can
      now be holding an active count on an earlier cell (cell->alias_of).  The
      purge scan passes by the earlier cell first, but this can't be got rid of
      until it has discarded the alias.  Ordinarily, afs_unuse_cell() would
      handle this by setting the management timer to trigger another pass - but
      afs_set_cell_timer() doesn't do anything if the namespace is being removed
      (net->live == false).  rmmod then hangs in the wait on cells_outstanding in
      afs_cell_purge().
      
      Fix this by making afs_set_cell_timer() directly queue the cell manager if
      net->live is false.  This causes additional management passes.
      
      Queueing the cell manager increments cells_outstanding to make sure the
      wait won't complete until all cells are destroyed.
      
      Fixes: 8a070a96 ("afs: Detect cell aliases 1 - Cells with root volumes")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      286377f6
    • D
      afs: Fix cell refcounting by splitting the usage counter · 88c853c3
      David Howells 提交于
      Management of the lifetime of afs_cell struct has some problems due to the
      usage counter being used to determine whether objects of that type are in
      use in addition to whether anyone might be interested in the structure.
      
      This is made trickier by cell objects being cached for a period of time in
      case they're quickly reused as they hold the result of a setup process that
      may be slow (DNS lookups, AFS RPC ops).
      
      Problems include the cached root volume from alias resolution pinning its
      parent cell record, rmmod occasionally hanging and occasionally producing
      assertion failures.
      
      Fix this by splitting the count of active users from the struct reference
      count.  Things then work as follows:
      
       (1) The cell cache keeps +1 on the cell's activity count and this has to
           be dropped before the cell can be removed.  afs_manage_cell() tries to
           exchange the 1 to a 0 with the cells_lock write-locked, and if
           successful, the record is removed from the net->cells.
      
       (2) One struct ref is 'owned' by the activity count.  That is put when the
           active count is reduced to 0 (final_destruction label).
      
       (3) A ref can be held on a cell whilst it is queued for management on a
           work queue without confusing the active count.  afs_queue_cell() is
           added to wrap this.
      
       (4) The queue's ref is dropped at the end of the management.  This is
           split out into a separate function, afs_manage_cell_work().
      
       (5) The root volume record is put after a cell is removed (at the
           final_destruction label) rather then in the RCU destruction routine.
      
       (6) Volumes hold struct refs, but aren't active users.
      
       (7) Both counts are displayed in /proc/net/afs/cells.
      
      There are some management function changes:
      
       (*) afs_put_cell() now just decrements the refcount and triggers the RCU
           destruction if it becomes 0.  It no longer sets a timer to have the
           manager do this.
      
       (*) afs_use_cell() and afs_unuse_cell() are added to increase and decrease
           the active count.  afs_unuse_cell() sets the management timer.
      
       (*) afs_queue_cell() is added to queue a cell with approprate refs.
      
      There are also some other fixes:
      
       (*) Don't let /proc/net/afs/cells access a cell's vllist if it's NULL.
      
       (*) Make sure that candidate cells in lookups are properly destroyed
           rather than being simply kfree'd.  This ensures the bits it points to
           are destroyed also.
      
       (*) afs_dec_cells_outstanding() is now called in cell destruction rather
           than at "final_destruction".  This ensures that cell->net is still
           valid to the end of the destructor.
      
       (*) As a consequence of the previous two changes, move the increment of
           net->cells_outstanding that was at the point of insertion into the
           tree to the allocation routine to correctly balance things.
      
      Fixes: 989782dc ("afs: Overhaul cell database management")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      88c853c3
    • D
      afs: Fix rapid cell addition/removal by not using RCU on cells tree · 92e3cc91
      David Howells 提交于
      There are a number of problems that are being seen by the rapidly mounting
      and unmounting an afs dynamic root with an explicit cell and volume
      specified (which should probably be rejected, but that's a separate issue):
      
      What the tests are doing is to look up/create a cell record for the name
      given and then tear it down again without actually using it to try to talk
      to a server.  This is repeated endlessly, very fast, and the new cell
      collides with the old one if it's not quick enough to reuse it.
      
      It appears (as suggested by Hillf Danton) that the search through the RB
      tree under a read_seqbegin_or_lock() under RCU conditions isn't safe and
      that it's not blocking the write_seqlock(), despite taking two passes at
      it.  He suggested that the code should take a ref on the cell it's
      attempting to look at - but this shouldn't be necessary until we've
      compared the cell names.  It's possible that I'm missing a barrier
      somewhere.
      
      However, using an RCU search for this is overkill, really - we only need to
      access the cell name in a few places, and they're places where we're may
      end up sleeping anyway.
      
      Fix this by switching to an R/W semaphore instead.
      
      Additionally, draw the down_read() call inside the function (renamed to
      afs_find_cell()) since all the callers were taking the RCU read lock (or
      should've been[*]).
      
      [*] afs_probe_cell_name() should have been, but that doesn't appear to be
      involved in the bug reports.
      
      The symptoms of this look like:
      
      	general protection fault, probably for non-canonical address 0xf27d208691691fdb: 0000 [#1] PREEMPT SMP KASAN
      	KASAN: maybe wild-memory-access in range [0x93e924348b48fed8-0x93e924348b48fedf]
      	...
      	RIP: 0010:strncasecmp lib/string.c:52 [inline]
      	RIP: 0010:strncasecmp+0x5f/0x240 lib/string.c:43
      	 afs_lookup_cell_rcu+0x313/0x720 fs/afs/cell.c:88
      	 afs_lookup_cell+0x2ee/0x1440 fs/afs/cell.c:249
      	 afs_parse_source fs/afs/super.c:290 [inline]
      	...
      
      Fixes: 989782dc ("afs: Overhaul cell database management")
      Reported-by: syzbot+459a5dce0b4cb70fd076@syzkaller.appspotmail.com
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      cc: Hillf Danton <hdanton@sina.com>
      cc: syzkaller-bugs@googlegroups.com
      92e3cc91
  4. 09 10月, 2020 1 次提交
    • D
      afs: Fix deadlock between writeback and truncate · ec0fa0b6
      David Howells 提交于
      The afs filesystem has a lock[*] that it uses to serialise I/O operations
      going to the server (vnode->io_lock), as the server will only perform one
      modification operation at a time on any given file or directory.  This
      prevents the the filesystem from filling up all the call slots to a server
      with calls that aren't going to be executed in parallel anyway, thereby
      allowing operations on other files to obtain slots.
      
        [*] Note that is probably redundant for directories at least since
            i_rwsem is used to serialise directory modifications and
            lookup/reading vs modification.  The server does allow parallel
            non-modification ops, however.
      
      When a file truncation op completes, we truncate the in-memory copy of the
      file to match - but we do it whilst still holding the io_lock, the idea
      being to prevent races with other operations.
      
      However, if writeback starts in a worker thread simultaneously with
      truncation (whilst notify_change() is called with i_rwsem locked, writeback
      pays it no heed), it may manage to set PG_writeback bits on the pages that
      will get truncated before afs_setattr_success() manages to call
      truncate_pagecache().  Truncate will then wait for those pages - whilst
      still inside io_lock:
      
          # cat /proc/8837/stack
          [<0>] wait_on_page_bit_common+0x184/0x1e7
          [<0>] truncate_inode_pages_range+0x37f/0x3eb
          [<0>] truncate_pagecache+0x3c/0x53
          [<0>] afs_setattr_success+0x4d/0x6e
          [<0>] afs_wait_for_operation+0xd8/0x169
          [<0>] afs_do_sync_operation+0x16/0x1f
          [<0>] afs_setattr+0x1fb/0x25d
          [<0>] notify_change+0x2cf/0x3c4
          [<0>] do_truncate+0x7f/0xb2
          [<0>] do_sys_ftruncate+0xd1/0x104
          [<0>] do_syscall_64+0x2d/0x3a
          [<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9
      
      The writeback operation, however, stalls indefinitely because it needs to
      get the io_lock to proceed:
      
          # cat /proc/5940/stack
          [<0>] afs_get_io_locks+0x58/0x1ae
          [<0>] afs_begin_vnode_operation+0xc7/0xd1
          [<0>] afs_store_data+0x1b2/0x2a3
          [<0>] afs_write_back_from_locked_page+0x418/0x57c
          [<0>] afs_writepages_region+0x196/0x224
          [<0>] afs_writepages+0x74/0x156
          [<0>] do_writepages+0x2d/0x56
          [<0>] __writeback_single_inode+0x84/0x207
          [<0>] writeback_sb_inodes+0x238/0x3cf
          [<0>] __writeback_inodes_wb+0x68/0x9f
          [<0>] wb_writeback+0x145/0x26c
          [<0>] wb_do_writeback+0x16a/0x194
          [<0>] wb_workfn+0x74/0x177
          [<0>] process_one_work+0x174/0x264
          [<0>] worker_thread+0x117/0x1b9
          [<0>] kthread+0xec/0xf1
          [<0>] ret_from_fork+0x1f/0x30
      
      and thus deadlock has occurred.
      
      Note that whilst afs_setattr() calls filemap_write_and_wait(), the fact
      that the caller is holding i_rwsem doesn't preclude more pages being
      dirtied through an mmap'd region.
      
      Fix this by:
      
       (1) Use the vnode validate_lock to mediate access between afs_setattr()
           and afs_writepages():
      
           (a) Exclusively lock validate_lock in afs_setattr() around the whole
           	 RPC operation.
      
           (b) If WB_SYNC_ALL isn't set on entry to afs_writepages(), trying to
           	 shared-lock validate_lock and returning immediately if we couldn't
           	 get it.
      
           (c) If WB_SYNC_ALL is set, wait for the lock.
      
           The validate_lock is also used to validate a file and to zap its cache
           if the file was altered by a third party, so it's probably a good fit
           for this.
      
       (2) Move the truncation outside of the io_lock in setattr, using the same
           hook as is used for local directory editing.
      
           This requires the old i_size to be retained in the operation record as
           we commit the revised status to the inode members inside the io_lock
           still, but we still need to know if we reduced the file size.
      
      Fixes: d2ddc776 ("afs: Overhaul volume and server record caching and fileserver rotation")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      ec0fa0b6
  5. 25 9月, 2020 1 次提交
  6. 28 8月, 2020 1 次提交
  7. 24 8月, 2020 1 次提交
  8. 22 8月, 2020 1 次提交
    • D
      afs: Fix NULL deref in afs_dynroot_depopulate() · 5e0b17b0
      David Howells 提交于
      If an error occurs during the construction of an afs superblock, it's
      possible that an error occurs after a superblock is created, but before
      we've created the root dentry.  If the superblock has a dynamic root
      (ie.  what's normally mounted on /afs), the afs_kill_super() will call
      afs_dynroot_depopulate() to unpin any created dentries - but this will
      oops if the root hasn't been created yet.
      
      Fix this by skipping that bit of code if there is no root dentry.
      
      This leads to an oops looking like:
      
      	general protection fault, ...
      	KASAN: null-ptr-deref in range [0x0000000000000068-0x000000000000006f]
      	...
      	RIP: 0010:afs_dynroot_depopulate+0x25f/0x529 fs/afs/dynroot.c:385
      	...
      	Call Trace:
      	 afs_kill_super+0x13b/0x180 fs/afs/super.c:535
      	 deactivate_locked_super+0x94/0x160 fs/super.c:335
      	 afs_get_tree+0x1124/0x1460 fs/afs/super.c:598
      	 vfs_get_tree+0x89/0x2f0 fs/super.c:1547
      	 do_new_mount fs/namespace.c:2875 [inline]
      	 path_mount+0x1387/0x2070 fs/namespace.c:3192
      	 do_mount fs/namespace.c:3205 [inline]
      	 __do_sys_mount fs/namespace.c:3413 [inline]
      	 __se_sys_mount fs/namespace.c:3390 [inline]
      	 __x64_sys_mount+0x27f/0x300 fs/namespace.c:3390
      	 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46
      	 entry_SYSCALL_64_after_hwframe+0x44/0xa9
      
      which is oopsing on this line:
      
      	inode_lock(root->d_inode);
      
      presumably because sb->s_root was NULL.
      
      Fixes: 0da0b7fd ("afs: Display manually added cells in dynamic root mount")
      Reported-by: syzbot+c1eff8205244ae7e11a6@syzkaller.appspotmail.com
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      5e0b17b0
  9. 21 8月, 2020 6 次提交
  10. 17 7月, 2020 1 次提交
  11. 16 7月, 2020 1 次提交
    • D
      afs: Fix interruption of operations · 811f04ba
      David Howells 提交于
      The afs filesystem driver allows unstarted operations to be cancelled by
      signal, but most of these can easily be restarted (mkdir for example).  The
      primary culprits for reproducing this are those applications that use
      SIGALRM to display a progress counter.
      
      File lock-extension operation is marked uninterruptible as we have a
      limited time in which to do it, and the release op is marked
      uninterruptible also as if we fail to unlock a file, we'll have to wait 20
      mins before anyone can lock it again.
      
      The store operation logs a warning if it gets interruption, e.g.:
      
      	kAFS: Unexpected error from FS.StoreData -4
      
      because it's run from the background - but it can also be run from
      fdatasync()-type things.  However, store options aren't marked
      interruptible at the moment.
      
      Fix this in the following ways:
      
       (1) Mark store operations as uninterruptible.  It might make sense to
           relax this for certain situations, but I'm not sure how to make sure
           that background store ops aren't affected by signals to foreground
           processes that happen to trigger them.
      
       (2) In afs_get_io_locks(), where we're getting the serialisation lock for
           talking to the fileserver, return ERESTARTSYS rather than EINTR
           because a lot of the operations (e.g. mkdir) are restartable if we
           haven't yet started sending the op to the server.
      
      Fixes: e49c7b2f ("afs: Build an abstraction around an "operation" concept")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      811f04ba
  12. 28 6月, 2020 1 次提交
  13. 21 6月, 2020 2 次提交
    • D
      afs: Fix hang on rmmod due to outstanding timer · 5481fc6e
      David Howells 提交于
      The fileserver probe timer, net->fs_probe_timer, isn't cancelled when
      the kafs module is being removed and so the count it holds on
      net->servers_outstanding doesn't get dropped..
      
      This causes rmmod to wait forever.  The hung process shows a stack like:
      
      	afs_purge_servers+0x1b5/0x23c [kafs]
      	afs_net_exit+0x44/0x6e [kafs]
      	ops_exit_list+0x72/0x93
      	unregister_pernet_operations+0x14c/0x1ba
      	unregister_pernet_subsys+0x1d/0x2a
      	afs_exit+0x29/0x6f [kafs]
      	__do_sys_delete_module.isra.0+0x1a2/0x24b
      	do_syscall_64+0x51/0x95
      	entry_SYSCALL_64_after_hwframe+0x44/0xa9
      
      Fix this by:
      
       (1) Attempting to cancel the probe timer and, if successful, drop the
           count that the timer was holding.
      
       (2) Make the timer function just drop the count and not schedule the
           prober if the afs portion of net namespace is being destroyed.
      
      Also, whilst we're at it, make the following changes:
      
       (3) Initialise net->servers_outstanding to 1 and decrement it before
           waiting on it so that it doesn't generate wake up events by being
           decremented to 0 until we're cleaning up.
      
       (4) Switch the atomic_dec() on ->servers_outstanding for ->fs_timer in
           afs_purge_servers() to use the helper function for that.
      
      Fixes: f6cbb368 ("afs: Actively poll fileservers to maintain NAT or firewall openings")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      5481fc6e
    • D
      afs: Fix afs_do_lookup() to call correct fetch-status op variant · f8ea5c7b
      David Howells 提交于
      Fix afs_do_lookup()'s fallback case for when FS.InlineBulkStatus isn't
      supported by the server.
      
      In the fallback, it calls FS.FetchStatus for the specific vnode it's
      meant to be looking up.  Commit b6489a49 broke this by renaming one
      of the two identically-named afs_fetch_status_operation descriptors to
      something else so that one of them could be made non-static.  The site
      that used the renamed one, however, wasn't renamed and didn't produce
      any warning because the other was declared in a header.
      
      Fix this by making afs_do_lookup() use the renamed variant.
      
      Note that there are two variants of the success method because one is
      called from ->lookup() where we may or may not have an inode, but can't
      call iget until after we've talked to the server - whereas the other is
      called from within iget where we have an inode, but it may or may not be
      initialised.
      
      The latter variant expects there to be an inode, but because it's being
      called from there former case, there might not be - resulting in an oops
      like the following:
      
        BUG: kernel NULL pointer dereference, address: 00000000000000b0
        ...
        RIP: 0010:afs_fetch_status_success+0x27/0x7e
        ...
        Call Trace:
          afs_wait_for_operation+0xda/0x234
          afs_do_lookup+0x2fe/0x3c1
          afs_lookup+0x3c5/0x4bd
          __lookup_slow+0xcd/0x10f
          walk_component+0xa2/0x10c
          path_lookupat.isra.0+0x80/0x110
          filename_lookup+0x81/0x104
          vfs_statx+0x76/0x109
          __do_sys_newlstat+0x39/0x6b
          do_syscall_64+0x4c/0x78
          entry_SYSCALL_64_after_hwframe+0x44/0xa9
      
      Fixes: b6489a49 ("afs: Fix silly rename")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      f8ea5c7b
  14. 17 6月, 2020 1 次提交
    • D
      afs: Fix silly rename · b6489a49
      David Howells 提交于
      Fix AFS's silly rename by the following means:
      
       (1) Set the destination directory in afs_do_silly_rename() so as to avoid
           misbehaviour and indicate that the directory data version will
           increment by 1 so as to avoid warnings about unexpected changes in the
           DV.  Also indicate that the ctime should be updated to avoid xfstest
           grumbling.
      
       (2) Note when the server indicates that a directory changed more than we
           expected (AFS_OPERATION_DIR_CONFLICT), indicating a conflict with a
           third party change, checking on successful completion of unlink and
           rename.
      
           The problem is that the FS.RemoveFile RPC op doesn't report the status
           of the unlinked file, though YFS.RemoveFile2 does.  This can be
           mitigated by the assumption that if the directory DV cranked by
           exactly 1, we can be sure we removed one link from the file; further,
           ordinarily in AFS, files cannot be hardlinked across directories, so
           if we reduce nlink to 0, the file is deleted.
      
           However, if the directory DV jumps by more than 1, we cannot know if a
           third party intervened by adding or removing a link on the file we
           just removed a link from.
      
           The same also goes for any vnode that is at the destination of the
           FS.Rename RPC op.
      
       (3) Make afs_vnode_commit_status() apply the nlink drop inside the cb_lock
           section along with the other attribute updates if ->op_unlinked is set
           on the descriptor for the appropriate vnode.
      
       (4) Issue a follow up status fetch to the unlinked file in the event of a
           third party conflict that makes it impossible for us to know if we
           actually deleted the file or not.
      
       (5) Provide a flag, AFS_VNODE_SILLY_DELETED, to make afs_getattr() lie to
           the user about the nlink of a silly deleted file so that it appears as
           0, not 1.
      
      Found with the generic/035 and generic/084 xfstests.
      
      Fixes: e49c7b2f ("afs: Build an abstraction around an "operation" concept")
      Reported-by: NMarc Dionne <marc.dionne@auristor.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      b6489a49
  15. 16 6月, 2020 5 次提交
  16. 15 6月, 2020 6 次提交
    • D
      afs: Fix the mapping of the UAEOVERFLOW abort code · 4ec89596
      David Howells 提交于
      Abort code UAEOVERFLOW is returned when we try and set a time that's out of
      range, but it's currently mapped to EREMOTEIO by the default case.
      
      Fix UAEOVERFLOW to map instead to EOVERFLOW.
      
      Found with the generic/258 xfstest.  Note that the test is wrong as it
      assumes that the filesystem will support a pre-UNIX-epoch date.
      
      Fixes: 1eda8bab ("afs: Add support for the UAE error table")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      4ec89596
    • D
      afs: Fix truncation issues and mmap writeback size · 793fe82e
      David Howells 提交于
      Fix the following issues:
      
       (1) Fix writeback to reduce the size of a store operation to i_size,
           effectively discarding the extra data.
      
           The problem comes when afs_page_mkwrite() records that a page is about
           to be modified by mmap().  It doesn't know what bits of the page are
           going to be modified, so it records the whole page as being dirty
           (this is stored in page->private as start and end offsets).
      
           Without this, the marshalling for the store to the server extends the
           size of the file to the end of the page (in afs_fs_store_data() and
           yfs_fs_store_data()).
      
       (2) Fix setattr to actually truncate the pagecache, thereby clearing
           the discarded part of a file.
      
       (3) Fix setattr to check that the new size is okay and to disable
           ATTR_SIZE if i_size wouldn't change.
      
       (4) Force i_size to be updated as the result of a truncate.
      
       (5) Don't truncate if ATTR_SIZE is not set.
      
       (6) Call pagecache_isize_extended() if the file was enlarged.
      
      Note that truncate_set_size() isn't used because the setting of i_size is
      done inside afs_vnode_commit_status() under the vnode->cb_lock.
      
      Found with the generic/029 and generic/393 xfstests.
      
      Fixes: 31143d5d ("AFS: implement basic file write support")
      Fixes: 4343d008 ("afs: Get rid of the afs_writeback record")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      793fe82e
    • D
      afs: Concoct ctimes · da8d0755
      David Howells 提交于
      The in-kernel afs filesystem ignores ctime because the AFS fileserver
      protocol doesn't support ctimes.  This, however, causes various xfstests to
      fail.
      
      Work around this by:
      
       (1) Setting ctime to attr->ia_ctime in afs_setattr().
      
       (2) Not ignoring ATTR_MTIME_SET, ATTR_TIMES_SET and ATTR_TOUCH settings.
      
       (3) Setting the ctime from the server mtime when on the target file when
           creating a hard link to it.
      
       (4) Setting the ctime on directories from their revised mtimes when
           renaming/moving a file.
      
      Found by the generic/221 and generic/309 xfstests.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      da8d0755
    • D
      afs: Fix EOF corruption · 3f4aa981
      David Howells 提交于
      When doing a partial writeback, afs_write_back_from_locked_page() may
      generate an FS.StoreData RPC request that writes out part of a file when a
      file has been constructed from pieces by doing seek, write, seek, write,
      ... as is done by ld.
      
      The FS.StoreData RPC is given the current i_size as the file length, but
      the server basically ignores it unless the data length is 0 (in which case
      it's just a truncate operation).  The revised file length returned in the
      result of the RPC may then not reflect what we suggested - and this leads
      to i_size getting moved backwards - which causes issues later.
      
      Fix the client to take account of this by ignoring the returned file size
      unless the data version number jumped unexpectedly - in which case we're
      going to have to clear the pagecache and reload anyway.
      
      This can be observed when doing a kernel build on an AFS mount.  The
      following pair of commands produce the issue:
      
        ld -m elf_x86_64 -z max-page-size=0x200000 --emit-relocs \
            -T arch/x86/realmode/rm/realmode.lds \
            arch/x86/realmode/rm/header.o \
            arch/x86/realmode/rm/trampoline_64.o \
            arch/x86/realmode/rm/stack.o \
            arch/x86/realmode/rm/reboot.o \
            -o arch/x86/realmode/rm/realmode.elf
        arch/x86/tools/relocs --realmode \
            arch/x86/realmode/rm/realmode.elf \
            >arch/x86/realmode/rm/realmode.relocs
      
      This results in the latter giving:
      
      	Cannot read ELF section headers 0/18: Success
      
      as the realmode.elf file got corrupted.
      
      The sequence of events can also be driven with:
      
      	xfs_io -t -f \
      		-c "pwrite -S 0x58 0 0x58" \
      		-c "pwrite -S 0x59 10000 1000" \
      		-c "close" \
      		/afs/example.com/scratch/a
      
      Fixes: 31143d5d ("AFS: implement basic file write support")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      3f4aa981
    • D
      afs: afs_write_end() should change i_size under the right lock · 1f32ef79
      David Howells 提交于
      Fix afs_write_end() to change i_size under vnode->cb_lock rather than
      ->wb_lock so that it doesn't race with afs_vnode_commit_status() and
      afs_getattr().
      
      The ->wb_lock is only meant to guard access to ->wb_keys which isn't
      accessed by that piece of code.
      
      Fixes: 4343d008 ("afs: Get rid of the afs_writeback record")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      1f32ef79
    • D
      afs: Fix non-setting of mtime when writing into mmap · bb413489
      David Howells 提交于
      The mtime on an inode needs to be updated when a write is made into an
      mmap'ed section.  There are three ways in which this could be done: update
      it when page_mkwrite is called, update it when a page is changed from dirty
      to writeback or leave it to the server and fix the mtime up from the reply
      to the StoreData RPC.
      
      Found with the generic/215 xfstest.
      
      Fixes: 1cf7a151 ("afs: Implement shared-writeable mmap")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      bb413489