1. 15 5月, 2019 1 次提交
    • D
      afs: Fix key leak in afs_release() and afs_evict_inode() · a1b879ee
      David Howells 提交于
      Fix afs_release() to go through the cleanup part of the function if
      FMODE_WRITE is set rather than exiting through vfs_fsync() (which skips the
      cleanup).  The cleanup involves discarding the refs on the key used for
      file ops and the writeback key record.
      
      Also fix afs_evict_inode() to clean up any left over wb keys attached to
      the inode/vnode when it is removed.
      
      Fixes: 5a813276 ("afs: Do better accretion of small writes on newly created content")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      a1b879ee
  2. 07 5月, 2019 2 次提交
    • M
      afs: Calculate i_blocks based on file size · c0abbb57
      Marc Dionne 提交于
      While it's not possible to give an accurate number for the blocks
      used on the server, populate i_blocks based on the file size so
      that 'du' can give a reasonable estimate.
      
      The value is rounded up to 1K granularity, for consistency with
      what other AFS clients report, and the servers' 1K usage quota
      unit.  Note that the value calculated by 'du' at the root of a
      volume can still be slightly lower than the quota usage on the
      server, as 0-length files are charged 1 quota block, but are
      reported as occupying 0 blocks.  Again, this is consistent with
      other AFS clients.
      Signed-off-by: NMarc Dionne <marc.dionne@auristor.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      c0abbb57
    • D
      afs: Log more information for "kAFS: AFS vnode with undefined type\n" · b134d687
      David Howells 提交于
      Log more information when "kAFS: AFS vnode with undefined type\n" is
      displayed due to a vnode record being retrieved from the server that
      appears to have a duff file type (usually 0).  This prints more information
      to try and help pin down the problem.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      b134d687
  3. 25 4月, 2019 1 次提交
    • D
      afs: Implement sillyrename for unlink and rename · 79ddbfa5
      David Howells 提交于
      Implement sillyrename for AFS unlink and rename, using the NFS variant
      implementation as a basis.
      
      Note that the asynchronous file locking extender/releaser has to be
      notified with a state change to stop it complaining if there's a race
      between that and the actual file deletion.
      
      A tracepoint, afs_silly_rename, is also added to note the silly rename and
      the cleanup.  The afs_edit_dir tracepoint is given some extra reason
      indicators and the afs_flock_ev tracepoint is given a silly-delete file
      lock cancellation indicator.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      79ddbfa5
  4. 13 4月, 2019 1 次提交
  5. 17 1月, 2019 2 次提交
    • D
      afs: Fix key refcounting in file locking code · 59d49076
      David Howells 提交于
      Fix the refcounting of the authentication keys in the file locking code.
      The vnode->lock_key member points to a key on which it expects to be
      holding a ref, but it isn't always given an extra ref, however.
      
      Fixes: 0fafdc9f ("afs: Fix file locking")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      59d49076
    • M
      afs: Don't set vnode->cb_s_break in afs_validate() · 4882a27c
      Marc Dionne 提交于
      A cb_interest record is not necessarily attached to the vnode on entry to
      afs_validate(), which can cause an oops when we try to bring the vnode's
      cb_s_break up to date in the default case (ie. no current callback promise
      and the vnode has not been deleted).
      
      Fix this by simply removing the line, as vnode->cb_s_break will be set when
      needed by afs_register_server_cb_interest() when we next get a callback
      promise from RPC call.
      
      The oops looks something like:
      
          BUG: unable to handle kernel NULL pointer dereference at 0000000000000018
          ...
          RIP: 0010:afs_validate+0x66/0x250 [kafs]
          ...
          Call Trace:
           afs_d_revalidate+0x8d/0x340 [kafs]
           ? __d_lookup+0x61/0x150
           lookup_dcache+0x44/0x70
           ? lookup_dcache+0x44/0x70
           __lookup_hash+0x24/0xa0
           do_unlinkat+0x11d/0x2c0
           __x64_sys_unlink+0x23/0x30
           do_syscall_64+0x4d/0xf0
           entry_SYSCALL_64_after_hwframe+0x44/0xa9
      
      Fixes: ae3b7361 ("afs: Fix validation/callback interaction")
      Signed-off-by: NMarc Dionne <marc.dionne@auristor.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      4882a27c
  6. 30 11月, 2018 1 次提交
    • D
      afs: Fix validation/callback interaction · ae3b7361
      David Howells 提交于
      When afs_validate() is called to validate a vnode (inode), there are two
      unhandled cases in the fastpath at the top of the function:
      
       (1) If the vnode is promised (AFS_VNODE_CB_PROMISED is set), the break
           counters match and the data has expired, then there's an implicit case
           in which the vnode needs revalidating.
      
           This has no consequences since the default "valid = false" set at the
           top of the function happens to do the right thing.
      
       (2) If the vnode is not promised and it hasn't been deleted
           (AFS_VNODE_DELETED is not set) then there's a default case we're not
           handling in which the vnode is invalid.  If the vnode is invalid, we
           need to bring cb_s_break and cb_v_break up to date before we refetch
           the status.
      
           As a consequence, once the server loses track of the client
           (ie. sufficient time has passed since we last sent it an operation),
           it will send us a CB.InitCallBackState* operation when we next try to
           talk to it.  This calls afs_init_callback_state() which increments
           afs_server::cb_s_break, but this then doesn't propagate to the
           afs_vnode record.
      
           The result being that every afs_validate() call thereafter sends a
           status fetch operation to the server.
      
      Clarify and fix this by:
      
       (A) Setting valid in all the branches rather than initialising it at the
           top so that the compiler catches where we've missed.
      
       (B) Restructuring the logic in the 'promised' branch so that we set valid
           to false if the callback is due to expire (or has expired) and so that
           the final case is that the vnode is still valid.
      
       (C) Adding an else-statement that ups cb_s_break and cb_v_break if the
           promised and deleted cases don't match.
      
      Fixes: c435ee34 ("afs: Overhaul the callback handling")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
      ae3b7361
  7. 24 10月, 2018 3 次提交
  8. 14 5月, 2018 2 次提交
    • D
      afs: Fix whole-volume callback handling · 68251f0a
      David Howells 提交于
      It's possible for an AFS file server to issue a whole-volume notification
      that callbacks on all the vnodes in the file have been broken.  This is
      done for R/O and backup volumes (which don't have per-file callbacks) and
      for things like a volume being taken offline.
      
      Fix callback handling to detect whole-volume notifications, to track it
      across operations and to check it during inode validation.
      
      Fixes: c435ee34 ("afs: Overhaul the callback handling")
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      68251f0a
    • D
      afs: Fix directory page locking · b61f7dcf
      David Howells 提交于
      The afs directory loading code (primarily afs_read_dir()) locks all the
      pages that hold a directory's content blob to defend against
      getdents/getdents races and getdents/lookup races where the competitors
      issue conflicting reads on the same data.  As the reads will complete
      consecutively, they may retrieve different versions of the data and
      one may overwrite the data that the other is busy parsing.
      
      Fix this by not locking the pages at all, but rather by turning the
      validation lock into an rwsem and getting an exclusive lock on it whilst
      reading the data or validating the attributes and a shared lock whilst
      parsing the data.  Sharing the attribute validation lock should be fine as
      the data fetch will retrieve the attributes also.
      
      The individual page locks aren't needed at all as the only place they're
      being used is to serialise data loading.
      
      Without this patch, the:
      
       	if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
      		...
      	}
      
      part of afs_read_dir() may be skipped, leaving the pages unlocked when we
      hit the success: clause - in which case we try to unlock the not-locked
      pages, leading to the following oops:
      
        page:ffffe38b405b4300 count:3 mapcount:0 mapping:ffff98156c83a978 index:0x0
        flags: 0xfffe000001004(referenced|private)
        raw: 000fffe000001004 ffff98156c83a978 0000000000000000 00000003ffffffff
        raw: dead000000000100 dead000000000200 0000000000000001 ffff98156b27c000
        page dumped because: VM_BUG_ON_PAGE(!PageLocked(page))
        page->mem_cgroup:ffff98156b27c000
        ------------[ cut here ]------------
        kernel BUG at mm/filemap.c:1205!
        ...
        RIP: 0010:unlock_page+0x43/0x50
        ...
        Call Trace:
         afs_dir_iterate+0x789/0x8f0 [kafs]
         ? _cond_resched+0x15/0x30
         ? kmem_cache_alloc_trace+0x166/0x1d0
         ? afs_do_lookup+0x69/0x490 [kafs]
         ? afs_do_lookup+0x101/0x490 [kafs]
         ? key_default_cmp+0x20/0x20
         ? request_key+0x3c/0x80
         ? afs_lookup+0xf1/0x340 [kafs]
         ? __lookup_slow+0x97/0x150
         ? lookup_slow+0x35/0x50
         ? walk_component+0x1bf/0x490
         ? path_lookupat.isra.52+0x75/0x200
         ? filename_lookup.part.66+0xa0/0x170
         ? afs_end_vnode_operation+0x41/0x60 [kafs]
         ? __check_object_size+0x9c/0x171
         ? strncpy_from_user+0x4a/0x170
         ? vfs_statx+0x73/0xe0
         ? __do_sys_newlstat+0x39/0x70
         ? __x64_sys_getdents+0xc9/0x140
         ? __x64_sys_getdents+0x140/0x140
         ? do_syscall_64+0x5b/0x160
         ? entry_SYSCALL_64_after_hwframe+0x44/0xa9
      
      Fixes: f3ddee8d ("afs: Fix directory handling")
      Reported-by: NMarc Dionne <marc.dionne@auristor.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      b61f7dcf
  9. 10 4月, 2018 9 次提交
    • D
      afs: Trace protocol errors · 5f702c8e
      David Howells 提交于
      Trace protocol errors detected in afs.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      5f702c8e
    • D
      afs: Locally edit directory data for mkdir/create/unlink/... · 63a4681f
      David Howells 提交于
      Locally edit the contents of an AFS directory upon a successful inode
      operation that modifies that directory (such as mkdir, create and unlink)
      so that we can avoid the current practice of re-downloading the directory
      after each change.
      
      This is viable provided that the directory version number we get back from
      the modifying RPC op is exactly incremented by 1 from what we had
      previously.  The data in the directory contents is in a defined format that
      we have to parse locally to perform lookups and readdir, so modifying isn't
      a problem.
      
      If the edit fails, we just clear the VALID flag on the directory and it
      will be reloaded next time it is needed.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      63a4681f
    • D
      afs: Fix directory handling · f3ddee8d
      David Howells 提交于
      AFS directories are structured blobs that are downloaded just like files
      and then parsed by the lookup and readdir code and, as such, are currently
      handled in the pagecache like any other file, with the entire directory
      content being thrown away each time the directory changes.
      
      However, since the blob is a known structure and since the data version
      counter on a directory increases by exactly one for each change committed
      to that directory, we can actually edit the directory locally rather than
      fetching it from the server after each locally-induced change.
      
      What we can't do, though, is mix data from the server and data from the
      client since the server is technically at liberty to rearrange or compress
      a directory if it sees fit, provided it updates the data version number
      when it does so and breaks the callback (ie. sends a notification).
      
      Further, lookup with lookup-ahead, readdir and, when it arrives, local
      editing are likely want to scan the whole of a directory.
      
      So directory handling needs to be improved to maintain the coherency of the
      directory blob prior to permitting local directory editing.
      
      To this end:
      
       (1) If any directory page gets discarded, invalidate and reread the entire
           directory.
      
       (2) If readpage notes that if when it fetches a single page that the
           version number has changed, the entire directory is flagged for
           invalidation.
      
       (3) Read as much of the directory in one go as we can.
      
      Note that this removes local caching of directories in fscache for the
      moment as we can't pass the pages to fscache_read_or_alloc_pages() since
      page->lru is in use by the LRU.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      f3ddee8d
    • D
      afs: Keep track of invalid-before version for dentry coherency · a4ff7401
      David Howells 提交于
      Each afs dentry is tagged with the version that the parent directory was at
      last time it was validated and, currently, if this differs, the directory
      is scanned and the dentry is refreshed.
      
      However, this leads to an excessive amount of revalidation on directories
      that get modified on the client without conflict with another client.  We
      know there's no conflict because the parent directory's data version number
      got incremented by exactly 1 on any create, mkdir, unlink, etc., therefore
      we can trust the current state of the unaffected dentries when we perform a
      local directory modification.
      
      Optimise by keeping track of the last version of the parent directory that
      was changed outside of the client in the parent directory's vnode and using
      that to validate the dentries rather than the current version.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      a4ff7401
    • D
      afs: Rearrange status mapping · dd9fbcb8
      David Howells 提交于
      Rearrange the AFSFetchStatus to inode attribute mapping code in a number of
      ways:
      
       (1) Use an XDR structure rather than a series of incremented pointer
           accesses when decoding an AFSFetchStatus object.  This allows
           out-of-order decode.
      
       (2) Don't store the if_version value but rather just check it and abort if
           it's not something we can handle.
      
       (3) Store the owner and group in the status record as raw values rather
           than converting them to kuid/kgid.  Do that when they're mapped into
           i_uid/i_gid.
      
       (4) Validate the type and abort code up front and abort if they're wrong.
      
       (5) Split the inode attribute setting out into its own function from the
           XDR decode of an AFSFetchStatus object.  This allows it to be called
           from elsewhere too.
      
       (6) Differentiate changes to data from changes to metadata.
      
       (7) Use the split-out attribute mapping function from afs_iget().
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      dd9fbcb8
    • D
      afs: Make it possible to get the data version in readpage · 0c3a5ac2
      David Howells 提交于
      Store the data version number indicated by an FS.FetchData op into the read
      request structure so that it's accessible by the page reader.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      0c3a5ac2
    • D
      afs: Init inode before accessing cache · 5800db81
      David Howells 提交于
      We no longer parse symlinks when we get the inode to determine if this
      symlink is actually a mountpoint as we detect that by examining the mode
      instead (symlinks are always 0777 and mountpoints 0644).
      
      Access the cache after mapping the status so that we don't have to manually
      set the inode size now.
      
      Note that this may need adjusting if the disconnected operation is
      implemented as the file metadata may have to be obtained from the cache.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      5800db81
    • D
      afs: Introduce a statistics proc file · d55b4da4
      David Howells 提交于
      Introduce a proc file that displays a bunch of statistics for the AFS
      filesystem in the current network namespace.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      d55b4da4
    • D
      afs: Fix checker warnings · fe342cf7
      David Howells 提交于
      Fix warnings raised by checker, including:
      
       (*) Warnings raised by unequal comparison for the purposes of sorting,
           where the endianness doesn't matter:
      
      fs/afs/addr_list.c:246:21: warning: restricted __be16 degrades to integer
      fs/afs/addr_list.c:246:30: warning: restricted __be16 degrades to integer
      fs/afs/addr_list.c:248:21: warning: restricted __be32 degrades to integer
      fs/afs/addr_list.c:248:49: warning: restricted __be32 degrades to integer
      fs/afs/addr_list.c:283:21: warning: restricted __be16 degrades to integer
      fs/afs/addr_list.c:283:30: warning: restricted __be16 degrades to integer
      
       (*) afs_set_cb_interest() is not actually used and can be removed.
      
       (*) afs_cell_gc_delay() should be provided with a sysctl.
      
       (*) afs_cell_destroy() needs to use rcu_access_pointer() to read
           cell->vl_addrs.
      
       (*) afs_init_fs_cursor() should be static.
      
       (*) struct afs_vnode::permit_cache needs to be marked __rcu.
      
       (*) afs_server_rcu() needs to use rcu_access_pointer().
      
       (*) afs_destroy_server() should use rcu_access_pointer() on
           server->addresses as the server object is no longer accessible.
      
       (*) afs_find_server() casts __be16/__be32 values to int in order to
           directly compare them for the purpose of finding a match in a list,
           but is should also annotate the cast with __force to avoid checker
           warnings.
      
       (*) afs_check_permit() accesses vnode->permit_cache outside of the RCU
           readlock, though it doesn't then access the value; the extraneous
           access is deleted.
      
      False positives:
      
       (*) Conditional locking around the code in xdr_decode_AFSFetchStatus.  This
           can be dealt with in a separate patch.
      
      fs/afs/fsclient.c:148:9: warning: context imbalance in 'xdr_decode_AFSFetchStatus' - different lock contexts for basic block
      
       (*) Incorrect handling of seq-retry lock context balance:
      
      fs/afs/inode.c:455:38: warning: context imbalance in 'afs_getattr' - different
      lock contexts for basic block
      fs/afs/server.c:52:17: warning: context imbalance in 'afs_find_server' - different lock contexts for basic block
      fs/afs/server.c:128:17: warning: context imbalance in 'afs_find_server_by_uuid' - different lock contexts for basic block
      
      Errors:
      
       (*) afs_lookup_cell_rcu() needs to break out of the seq-retry loop, not go
           round again if it successfully found the workstation cell.
      
       (*) Fix UUID decode in afs_deliver_cb_probe_uuid().
      
       (*) afs_cache_permit() has a missing rcu_read_unlock() before one of the
           jumps to the someone_else_changed_it label.  Move the unlock to after
           the label.
      
       (*) afs_vl_get_addrs_u() is using ntohl() rather than htonl() when
           encoding to XDR.
      
       (*) afs_deliver_yfsvl_get_endpoints() is using htonl() rather than ntohl()
           when decoding from XDR.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      fe342cf7
  10. 06 4月, 2018 1 次提交
  11. 04 4月, 2018 3 次提交
    • D
      fscache: Attach the index key and aux data to the cookie · 402cb8dd
      David Howells 提交于
      Attach copies of the index key and auxiliary data to the fscache cookie so
      that:
      
       (1) The callbacks to the netfs for this stuff can be eliminated.  This
           can simplify things in the cache as the information is still
           available, even after the cache has relinquished the cookie.
      
       (2) Simplifies the locking requirements of accessing the information as we
           don't have to worry about the netfs object going away on us.
      
       (3) The cache can do lazy updating of the coherency information on disk.
           As long as the cache is flushed before reboot/poweroff, there's no
           need to update the coherency info on disk every time it changes.
      
       (4) Cookies can be hashed or put in a tree as the index key is easily
           available.  This allows:
      
           (a) Checks for duplicate cookies can be made at the top fscache layer
           	 rather than down in the bowels of the cache backend.
      
           (b) Caching can be added to a netfs object that has a cookie if the
           	 cache is brought online after the netfs object is allocated.
      
      A certain amount of space is made in the cookie for inline copies of the
      data, but if it won't fit there, extra memory will be allocated for it.
      
      The downside of this is that live cache operation requires more memory.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Acked-by: NAnna Schumaker <anna.schumaker@netapp.com>
      Tested-by: NSteve Dickson <steved@redhat.com>
      402cb8dd
    • D
      afs: Be more aggressive in retiring cached vnodes · 678edd09
      David Howells 提交于
      When relinquishing cookies, either due to iget failure or to inode
      eviction, retire a cookie if we think the corresponding vnode got deleted
      on the server rather than just letting it lie in the cache.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      678edd09
    • D
      afs: Invalidate cache on server data change · c1515999
      David Howells 提交于
      Invalidate any data stored in fscache for a vnode that changes on the
      server so that we don't end up with the cache in a bad state locally.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      c1515999
  12. 06 2月, 2018 1 次提交
    • D
      afs: Support the AFS dynamic root · 4d673da1
      David Howells 提交于
      Support the AFS dynamic root which is a pseudo-volume that doesn't connect
      to any server resource, but rather is just a root directory that
      dynamically creates mountpoint directories where the name of such a
      directory is the name of the cell.
      
      Such a mount can be created thus:
      
      	mount -t afs none /afs -o dyn
      
      Dynamic root superblocks aren't shared except by bind mounts and
      propagation.  Cell root volumes can then be mounted by referring to them by
      name, e.g.:
      
      	ls /afs/grand.central.org/
      	ls /afs/.grand.central.org/
      
      The kernel will upcall to consult the DNS if the address wasn't supplied
      directly.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      4d673da1
  13. 29 1月, 2018 1 次提交
    • J
      afs: convert to new i_version API · a01179e6
      Jeff Layton 提交于
      For AFS, it's generally treated as an opaque value, so we use the
      *_raw variants of the API here.
      
      Note that AFS has quite a different definition for this counter. AFS
      only increments it on changes to the data to the data in regular files
      and contents of the directories. Inode metadata changes do not result
      in a version increment.
      
      We'll need to reconcile that somehow if we ever want to present this to
      userspace via statx.
      Signed-off-by: NJeff Layton <jlayton@redhat.com>
      a01179e6
  14. 02 1月, 2018 1 次提交
    • D
      afs: Fix unlink · 440fbc3a
      David Howells 提交于
      Repeating creation and deletion of a file on an afs mount will run the box
      out of memory, e.g.:
      
      	dd if=/dev/zero of=/afs/scratch/m0 bs=$((1024*1024)) count=512
      	rm /afs/scratch/m0
      
      The problem seems to be that it's not properly decrementing the nlink count
      so that the inode can be scrapped.
      
      Note that this doesn't fix local creation followed by remote deletion.
      That's harder to handle and will require a separate patch as we're not told
      that the file has been deleted - only that the directory has changed.
      Reported-by: NMarc Dionne <marc.dionne@auristor.com>
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      440fbc3a
  15. 13 11月, 2017 6 次提交
    • D
      afs: Get rid of the afs_writeback record · 4343d008
      David Howells 提交于
      Get rid of the afs_writeback record that kAFS is using to match keys with
      writes made by that key.
      
      Instead, keep a list of keys that have a file open for writing and/or
      sync'ing and iterate through those.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      4343d008
    • D
      afs: Introduce a file-private data record · 215804a9
      David Howells 提交于
      Introduce a file-private data record for kAFS and put the key into it
      rather than storing the key in file->private_data.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      215804a9
    • D
      afs: Overhaul volume and server record caching and fileserver rotation · d2ddc776
      David Howells 提交于
      The current code assumes that volumes and servers are per-cell and are
      never shared, but this is not enforced, and, indeed, public cells do exist
      that are aliases of each other.  Further, an organisation can, say, set up
      a public cell and a private cell with overlapping, but not identical, sets
      of servers.  The difference is purely in the database attached to the VL
      servers.
      
      The current code will malfunction if it sees a server in two cells as it
      assumes global address -> server record mappings and that each server is in
      just one cell.
      
      Further, each server may have multiple addresses - and may have addresses
      of different families (IPv4 and IPv6, say).
      
      To this end, the following structural changes are made:
      
       (1) Server record management is overhauled:
      
           (a) Server records are made independent of cell.  The namespace keeps
           	 track of them, volume records have lists of them and each vnode
           	 has a server on which its callback interest currently resides.
      
           (b) The cell record no longer keeps a list of servers known to be in
           	 that cell.
      
           (c) The server records are now kept in a flat list because there's no
           	 single address to sort on.
      
           (d) Server records are now keyed by their UUID within the namespace.
      
           (e) The addresses for a server are obtained with the VL.GetAddrsU
           	 rather than with VL.GetEntryByName, using the server's UUID as a
           	 parameter.
      
           (f) Cached server records are garbage collected after a period of
           	 non-use and are counted out of existence before purging is allowed
           	 to complete.  This protects the work functions against rmmod.
      
           (g) The servers list is now in /proc/fs/afs/servers.
      
       (2) Volume record management is overhauled:
      
           (a) An RCU-replaceable server list is introduced.  This tracks both
           	 servers and their coresponding callback interests.
      
           (b) The superblock is now keyed on cell record and numeric volume ID.
      
           (c) The volume record is now tied to the superblock which mounts it,
           	 and is activated when mounted and deactivated when unmounted.
           	 This makes it easier to handle the cache cookie without causing a
           	 double-use in fscache.
      
           (d) The volume record is loaded from the VLDB using VL.GetEntryByNameU
           	 to get the server UUID list.
      
           (e) The volume name is updated if it is seen to have changed when the
           	 volume is updated (the update is keyed on the volume ID).
      
       (3) The vlocation record is got rid of and VLDB records are no longer
           cached.  Sufficient information is stored in the volume record, though
           an update to a volume record is now no longer shared between related
           volumes (volumes come in bundles of three: R/W, R/O and backup).
      
      and the following procedural changes are made:
      
       (1) The fileserver cursor introduced previously is now fleshed out and
           used to iterate over fileservers and their addresses.
      
       (2) Volume status is checked during iteration, and the server list is
           replaced if a change is detected.
      
       (3) Server status is checked during iteration, and the address list is
           replaced if a change is detected.
      
       (4) The abort code is saved into the address list cursor and -ECONNABORTED
           returned in afs_make_call() if a remote abort happened rather than
           translating the abort into an error message.  This allows actions to
           be taken depending on the abort code more easily.
      
           (a) If a VMOVED abort is seen then this is handled by rechecking the
           	 volume and restarting the iteration.
      
           (b) If a VBUSY, VRESTARTING or VSALVAGING abort is seen then this is
               handled by sleeping for a short period and retrying and/or trying
               other servers that might serve that volume.  A message is also
               displayed once until the condition has cleared.
      
           (c) If a VOFFLINE abort is seen, then this is handled as VBUSY for the
           	 moment.
      
           (d) If a VNOVOL abort is seen, the volume is rechecked in the VLDB to
           	 see if it has been deleted; if not, the fileserver is probably
           	 indicating that the volume couldn't be attached and needs
           	 salvaging.
      
           (e) If statfs() sees one of these aborts, it does not sleep, but
           	 rather returns an error, so as not to block the umount program.
      
       (5) The fileserver iteration functions in vnode.c are now merged into
           their callers and more heavily macroised around the cursor.  vnode.c
           is removed.
      
       (6) Operations on a particular vnode are serialised on that vnode because
           the server will lock that vnode whilst it operates on it, so a second
           op sent will just have to wait.
      
       (7) Fileservers are probed with FS.GetCapabilities before being used.
           This is where service upgrade will be done.
      
       (8) A callback interest on a fileserver is set up before an FS operation
           is performed and passed through to afs_make_call() so that it can be
           set on the vnode if the operation returns a callback.  The callback
           interest is passed through to afs_iget() also so that it can be set
           there too.
      
      In general, record updating is done on an as-needed basis when we try to
      access servers, volumes or vnodes rather than offloading it to work items
      and special threads.
      
      Notes:
      
       (1) Pre AFS-3.4 servers are no longer supported, though this can be added
           back if necessary (AFS-3.4 was released in 1998).
      
       (2) VBUSY is retried forever for the moment at intervals of 1s.
      
       (3) /proc/fs/afs/<cell>/servers no longer exists.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      d2ddc776
    • D
      afs: Overhaul permit caching · be080a6f
      David Howells 提交于
      Overhaul permit caching in AFS by making it per-vnode and sharing permit
      lists where possible.
      
      When most of the fileserver operations are called, they return a status
      structure indicating the (revised) details of the vnode or vnodes involved
      in the operation.  This includes the access mark derived from the ACL
      (named CallerAccess in the protocol definition file).  This is cacheable
      and if the ACL changes, the server will tell us that it is breaking the
      callback promise, at which point we can discard the currently cached
      permits.
      
      With this patch, the afs_permits structure has, at the end, an array of
      { key, CallerAccess } elements, sorted by key pointer.  This is then cached
      in a hash table so that it can be shared between vnodes with the same
      access permits.
      
      Permit lists can only be shared if they contain the exact same set of
      key->CallerAccess mappings.
      
      Note that that table is global rather than being per-net_ns.  If the keys
      in a permit list cross net_ns boundaries, there is no problem sharing the
      cached permits, since the permits are just integer masks.
      
      Since permit lists pin keys, the permit cache also makes it easier for a
      future patch to find all occurrences of a key and remove them by means of
      setting the afs_permits::invalidated flag and then clearing the appropriate
      key pointer.  In such an event, memory barriers will need adding.
      
      Lastly, the permit caching is skipped if the server has sent either a
      vnode-specific or an entire-server callback since the start of the
      operation.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      be080a6f
    • D
      afs: Overhaul the callback handling · c435ee34
      David Howells 提交于
      Overhaul the AFS callback handling by the following means:
      
       (1) Don't give up callback promises on vnodes that we are no longer using,
           rather let them just expire on the server or let the server break
           them.  This is actually more efficient for the server as the callback
           lookup is expensive if there are lots of extant callbacks.
      
       (2) Only give up the callback promises we have from a server when the
           server record is destroyed.  Then we can just give up *all* the
           callback promises on it in one go.
      
       (3) Servers can end up being shared between cells if cells are aliased, so
           don't add all the vnodes being backed by a particular server into a
           big FID-indexed tree on that server as there may be duplicates.
      
           Instead have each volume instance (~= superblock) register an interest
           in a server as it starts to make use of it and use this to allow the
           processor for callbacks from the server to find the superblock and
           thence the inode corresponding to the FID being broken by means of
           ilookup_nowait().
      
       (4) Rather than iterating over the entire callback list when a mass-break
           comes in from the server, maintain a counter of mass-breaks in
           afs_server (cb_seq) and make afs_validate() check it against the copy
           in afs_vnode.
      
           It would be nice not to have to take a read_lock whilst doing this,
           but that's tricky without using RCU.
      
       (5) Save a ref on the fileserver we're using for a call in the afs_call
           struct so that we can access its cb_s_break during call decoding.
      
       (6) Write-lock around callback and status storage in a vnode and read-lock
           around getattr so that we don't see the status mid-update.
      
      This has the following consequences:
      
       (1) Data invalidation isn't seen until someone calls afs_validate() on a
           vnode.  Unfortunately, we need to use a key to query the server, but
           getting one from a background thread is tricky without caching loads
           of keys all over the place.
      
       (2) Mass invalidation isn't seen until someone calls afs_validate().
      
       (3) Callback breaking is going to hit the inode_hash_lock quite a bit.
           Could this be replaced with rcu_read_lock() since inodes are destroyed
           under RCU conditions.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      c435ee34
    • D
      afs: Push the net ns pointer to more places · 9ed900b1
      David Howells 提交于
      Push the network namespace pointer to more places in AFS, including the
      afs_server structure (which doesn't hold a ref on the netns).
      
      In particular, afs_put_cell() now takes requires a net ns parameter so that
      it can safely alter the netns after decrementing the cell usage count - the
      cell will be deallocated by a background thread after being cached for a
      period, which means that it's not safe to access it after reducing its
      usage count.
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      9ed900b1
  16. 10 7月, 2017 1 次提交
    • D
      afs: Add metadata xattrs · d3e3b7ea
      David Howells 提交于
      Add xattrs to allow the user to get/set metadata in lieu of having pioctl()
      available.  The following xattrs are now available:
      
       - "afs.cell"
      
         The name of the cell in which the vnode's volume resides.
      
       - "afs.fid"
      
         The volume ID, vnode ID and vnode uniquifier of the file as three hex
         numbers separated by colons.
      
       - "afs.volume"
      
         The name of the volume in which the vnode resides.
      
      For example:
      
      	# getfattr -d -m ".*" /mnt/scratch
      	getfattr: Removing leading '/' from absolute path names
      	# file: mnt/scratch
      	afs.cell="mycell.myorg.org"
      	afs.fid="10000b:1:1"
      	afs.volume="scratch"
      Signed-off-by: NDavid Howells <dhowells@redhat.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      d3e3b7ea
  17. 17 3月, 2017 4 次提交