1. 17 Mar, 2020 2 commits
    • Al Viro's avatar
      ovl: ovl_obtain_alias(): don't call d_instantiate_anon() for old · 504f3841
      Al Viro authored
      The situation is the same as for __d_obtain_alias() (which is what that
      thing is parallel to) - if we find a preexisting alias, we want to grab it,
      drop the inode and return the alias we'd found.
      
      The only thing d_instantiate_anon() does compared to that is spurious
      security_d_instiate() that has already been done to that dentry with exact
      same arguments.
      Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      504f3841
    • Miklos Szeredi's avatar
      ovl: decide if revalidate needed on a per-dentry basis · f4288844
      Miklos Szeredi authored
      Allow completely skipping ->revalidate() on a per-dentry basis, in case the
      underlying layers used for a dentry do not themselves have ->revalidate().
      
      E.g. negative overlay dentry has no underlying layers, hence revalidate is
      unnecessary.  Or if lower layer is remote but overlay dentry is pure-upper,
      then can skip revalidate.
      
      The following places need to update whether the dentry needs revalidate or
      not:
      
       - fill-super (root dentry)
       - lookup
       - create
       - fh_to_dentry
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      f4288844
  2. 24 Jan, 2020 1 commit
  3. 22 Jan, 2020 2 commits
  4. 10 Dec, 2019 1 commit
    • Amir Goldstein's avatar
      ovl: make sure that real fid is 32bit aligned in memory · cbe7fba8
      Amir Goldstein authored
      Seprate on-disk encoding from in-memory and on-wire resresentation
      of overlay file handle.
      
      In-memory and on-wire we only ever pass around pointers to struct
      ovl_fh, which encapsulates at offset 3 the on-disk format struct
      ovl_fb. struct ovl_fb encapsulates at offset 21 the real file handle.
      That makes sure that the real file handle is always 32bit aligned
      in-memory when passed down to the underlying filesystem.
      
      On-disk format remains the same and store/load are done into
      correctly aligned buffer.
      
      New nfs exported file handles are exported with aligned real fid.
      Old nfs file handles are copied to an aligned buffer before being
      decoded.
      Reported-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      cbe7fba8
  5. 11 Sep, 2019 1 commit
  6. 19 Jun, 2019 1 commit
  7. 26 Apr, 2019 1 commit
  8. 21 Nov, 2018 1 commit
    • Amir Goldstein's avatar
      ovl: fix decode of dir file handle with multi lower layers · 155b8a04
      Amir Goldstein authored
      When decoding a lower file handle, we first call ovl_check_origin_fh()
      with connected=false to get any real lower dentry for overlay inode
      cache lookup.
      
      If the real dentry is a disconnected dir dentry, ovl_check_origin_fh()
      is called again with connected=true to get a connected real dentry
      and find the lower layer the real dentry belongs to.
      
      If the first call returned a connected real dentry, we use it to
      lookup an overlay connected dentry, but the first ovl_check_origin_fh()
      call with connected=false did not check that the found dentry is under
      the root of the layer (see ovl_acceptable()), it only checked that
      the found dentry super block matches the uuid of the lower file handle.
      
      In case there are multiple lower layers on the same fs and the found
      dentry is not from the top most lower layer, using the layer index
      returned from the first ovl_check_origin_fh() is wrong and we end
      up failing to decode the file handle.
      
      Fix this by always calling ovl_check_origin_fh() with connected=true
      if we got a directory dentry in the first call.
      
      Fixes: 8b58924a ("ovl: lookup in inode cache first when decoding...")
      Cc: <stable@vger.kernel.org> # v4.17
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      155b8a04
  9. 20 Jul, 2018 1 commit
    • Vivek Goyal's avatar
      ovl: Modify ovl_lookup() and friends to lookup metacopy dentry · 9d3dfea3
      Vivek Goyal authored
      This patch modifies ovl_lookup() and friends to lookup metacopy dentries.
      It also allows for presence of metacopy dentries in lower layer.
      
      During lookup, check for presence of OVL_XATTR_METACOPY and if not present,
      set OVL_UPPERDATA bit in flags.
      
      We don't support metacopy feature with nfs_export.  So in nfs_export code,
      we set OVL_UPPERDATA flag set unconditionally if upper inode exists.
      
      Do not follow metacopy origin if we find a metacopy only inode and metacopy
      feature is not enabled for that mount.  Like redirect, this can have
      security implications where an attacker could hand craft upper and try to
      gain access to file on lower which it should not have to begin with.
      Signed-off-by: default avatarVivek Goyal <vgoyal@redhat.com>
      Reviewed-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      9d3dfea3
  10. 31 May, 2018 1 commit
  11. 12 Apr, 2018 5 commits
    • Amir Goldstein's avatar
      ovl: consistent i_ino for non-samefs with xino · 12574a9f
      Amir Goldstein authored
      When overlay layers are not all on the same fs, but all inode numbers
      of underlying fs do not use the high 'xino' bits, overlay st_ino values
      are constant and persistent.
      
      In that case, set i_ino value to the same value as st_ino for nfsd
      readdirplus validator.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      12574a9f
    • Vivek Goyal's avatar
      ovl: cleanup setting OVL_INDEX · 0471a9cd
      Vivek Goyal authored
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      0471a9cd
    • Amir Goldstein's avatar
      ovl: lookup in inode cache first when decoding lower file handle · 8b58924a
      Amir Goldstein authored
      When decoding a lower file handle, we need to check if lower file was
      copied up and indexed and if it has a whiteout index, we need to check
      if this is an unlinked but open non-dir before returning -ESTALE.
      
      To find out if this is an unlinked but open non-dir we need to lookup
      an overlay inode in inode cache by lower inode and that requires decoding
      the lower file handle before looking in inode cache.
      
      Before this change, if the lower inode turned out to be a directory, we
      may have paid an expensive cost to reconnect that lower directory for
      nothing.
      
      After this change, we start by decoding a disconnected lower dentry and
      using the lower inode for looking up an overlay inode in inode cache.
      If we find overlay inode and dentry in cache, we avoid the index lookup
      overhead. If we don't find an overlay inode and dentry in cache, then we
      only need to decode a connected lower dentry in case the lower dentry is
      a non-indexed directory.
      
      The xfstests group overlay/exportfs tests decoding overlayfs file
      handles after drop_caches with different states of the file at encode
      and decode time. Overall the tests in the group call ovl_lower_fh_to_d()
      89 times to decode a lower file handle.
      
      Before this change, the tests called ovl_get_index_fh() 75 times and
      reconnect_one() 61 times.
      After this change, the tests call ovl_get_index_fh() 70 times and
      reconnect_one() 59 times. The 2 cases where reconnect_one() was avoided
      are cases where a non-upper directory file handle was encoded, then the
      directory removed and then file handle was decoded.
      
      To demonstrate the affect on decoding file handles with hot inode/dentry
      cache, the drop_caches call in the tests was disabled. Without
      drop_caches, there are no reconnect_one() calls at all before or after
      the change. Before the change, there are 75 calls to ovl_get_index_fh(),
      exactly as the case with drop_caches. After the change, there are only
      10 calls to ovl_get_index_fh().
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      8b58924a
    • Amir Goldstein's avatar
      ovl: do not try to reconnect a disconnected origin dentry · 8a22efa1
      Amir Goldstein authored
      On lookup of non directory, we try to decode the origin file handle
      stored in upper inode. The origin file handle is supposed to be decoded
      to a disconnected non-dir dentry, which is fine, because we only need
      the lower inode of a copy up origin.
      
      However, if the origin file handle somehow turns out to be a directory
      we pay the expensive cost of reconnecting the directory dentry, only to
      get a mismatch file type and drop the dentry.
      
      Optimize this case by explicitly opting out of reconnecting the dentry.
      Opting-out of reconnect is done by passing a NULL acceptable callback
      to exportfs_decode_fh().
      
      While the case described above is a strange corner case that does not
      really need to be optimized, the API added for this optimization will
      be used by a following patch to optimize a more common case of decoding
      an overlayfs file handle.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      8a22efa1
    • Amir Goldstein's avatar
      ovl: disambiguate ovl_encode_fh() · 5b2cccd3
      Amir Goldstein authored
      Rename ovl_encode_fh() to ovl_encode_real_fh() to differentiate from the
      exportfs function ovl_encode_inode_fh() and change the latter to
      ovl_encode_fh() to match the exportfs method name.
      
      Rename ovl_decode_fh() to ovl_decode_real_fh() for consistency.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      5b2cccd3
  12. 26 Feb, 2018 1 commit
  13. 16 Feb, 2018 2 commits
    • Amir Goldstein's avatar
      ovl: check ERR_PTR() return value from ovl_lookup_real() · 7168179f
      Amir Goldstein authored
      Reported-by: default avatarDan Carpenter <dan.carpenter@oracle.com>
      Fixes: 06170154 ("ovl: lookup indexed ancestor of lower dir")
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      7168179f
    • Amir Goldstein's avatar
      ovl: check lower ancestry on encode of lower dir file handle · 2ca3c148
      Amir Goldstein authored
      This change relaxes copy up on encode of merge dir with lower layer > 1
      and handles the case of encoding a merge dir with lower layer 1, where an
      ancestor is a non-indexed merge dir. In that case, decode of the lower
      file handle will not have been possible if the non-indexed ancestor is
      redirected before or after encode.
      
      Before encoding a non-upper directory file handle from real layer N, we
      need to check if it will be possible to reconnect an overlay dentry from
      the real lower decoded dentry. This is done by following the overlay
      ancestry up to a "layer N connected" ancestor and verifying that all
      parents along the way are "layer N connectable". If an ancestor that is
      NOT "layer N connectable" is found, we need to copy up an ancestor, which
      is "layer N connectable", thus making that ancestor "layer N connected".
      For example:
      
       layer 1: /a
       layer 2: /a/b/c
      
      The overlay dentry /a is NOT "layer 2 connectable", because if dir /a is
      copied up and renamed, upper dir /a will be indexed by lower dir /a from
      layer 1. The dir /a from layer 2 will never be indexed, so the algorithm
      in ovl_lookup_real_ancestor() (*) will not be able to lookup a connected
      overlay dentry from the connected lower dentry /a/b/c.
      
      To avoid this problem on decode time, we need to copy up an ancestor of
      /a/b/c, which is "layer 2 connectable", on encode time. That ancestor is
      /a/b. After copy up (and index) of /a/b, it will become "layer 2 connected"
      and when the time comes to decode the file handle from lower dentry /a/b/c,
      ovl_lookup_real_ancestor() will find the indexed ancestor /a/b and decoding
      a connected overlay dentry will be accomplished.
      
      (*) the algorithm in ovl_lookup_real_ancestor() can be improved to lookup
      an entry /a in the lower layers above layer N and find the indexed dir /a
      from layer 1. If that improvement is made, then the check for "layer N
      connected" will need to verify there are no redirects in lower layers above
      layer N. In the example above, /a will be "layer 2 connectable". However,
      if layer 2 dir /a is a target of a layer 1 redirect, then /a will NOT be
      "layer 2 connectable":
      
       layer 1: /A (redirect = /a)
       layer 2: /a/b/c
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      2ca3c148
  14. 05 Feb, 2018 1 commit
  15. 24 Jan, 2018 13 commits
    • Amir Goldstein's avatar
      ovl: lookup indexed ancestor of lower dir · 06170154
      Amir Goldstein authored
      ovl_lookup_real() in lower layer walks back lower parents to find the
      topmost indexed parent. If an indexed ancestor is found before reaching
      lower layer root, ovl_lookup_real() is called recursively with upper
      layer to walk back from indexed upper to the topmost connected/hashed
      upper parent (or up to root).
      
      ovl_lookup_real() in upper layer then walks forward to connect the topmost
      upper overlay dir dentry and ovl_lookup_real() in lower layer continues to
      walk forward to connect the decoded lower overlay dir dentry.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      06170154
    • Amir Goldstein's avatar
      ovl: lookup connected ancestor of dir in inode cache · 4b91c30a
      Amir Goldstein authored
      Decoding a dir file handle requires walking backward up to layer root and
      for lower dir also checking the index to see if any of the parents have
      been copied up.
      
      Lookup overlay ancestor dentry in inode/dentry cache by decoded real
      parents to shortcut looking up all the way back to layer root.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      4b91c30a
    • Amir Goldstein's avatar
      ovl: decode pure lower dir file handles · 98892516
      Amir Goldstein authored
      Similar to decoding a pure upper dir file handle, decoding a pure lower
      dir file handle is implemented by looking an overlay dentry of the same
      path as the pure lower path and verifying that the overlay dentry's
      real lower matches the decoded real lower file handle.
      
      Unlike the case of upper dir file handle, the lookup of overlay path by
      lower real path can fail or find a mismatched overlay dentry if any of
      the lower parents have been copied up and renamed. To address this case
      we will need to check if any of the lower parents are indexed.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      98892516
    • Amir Goldstein's avatar
      ovl: decode indexed dir file handles · 3b0bfc6e
      Amir Goldstein authored
      Decoding an indexed dir file handle is done by looking up the file handle
      in index dir by name and then decoding the upper dir from the index origin
      file handle. The decoded upper path is used to lookup an overlay dentry of
      the same path.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      3b0bfc6e
    • Amir Goldstein's avatar
      ovl: decode lower file handles of unlinked but open files · 9436a1a3
      Amir Goldstein authored
      Lookup overlay inode in cache by origin inode, so we can decode a file
      handle of an open file even if the index has a whiteout index entry to
      mark this overlay inode was unlinked.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      9436a1a3
    • Amir Goldstein's avatar
      ovl: decode indexed non-dir file handles · f71bd9cf
      Amir Goldstein authored
      Decoding an indexed non-dir file handle is similar to decoding a lower
      non-dir file handle, but additionally, we lookup the file handle in index
      dir by name to find the real upper inode.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      f71bd9cf
    • Amir Goldstein's avatar
      ovl: decode lower non-dir file handles · f941866f
      Amir Goldstein authored
      Decoding a lower non-dir file handle is done by decoding the lower dentry
      from underlying lower fs, finding or allocating an overlay inode that is
      hashed by the real lower inode and instantiating an overlay dentry with
      that inode.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      f941866f
    • Amir Goldstein's avatar
      ovl: encode lower file handles · 03e1c584
      Amir Goldstein authored
      For indexed or lower non-dir, encode a non-connectable lower file handle
      from origin inode. For indexed or lower dir, when ofs->numlower == 1,
      encode a lower file handle from lower dir.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      03e1c584
    • Amir Goldstein's avatar
      ovl: copy up before encoding non-connectable dir file handle · 05e1f118
      Amir Goldstein authored
      Decoding a merge dir, whose origin's parent is under a redirected
      lower dir is not always possible. As a simple aproximation, we do
      not encode lower dir file handles when overlay has multiple lower
      layers and origin is below the topmost lower layer.
      
      We should later relax this condition and copy up only the parent
      that is under a redirected lower.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      05e1f118
    • Amir Goldstein's avatar
      ovl: encode non-indexed upper file handles · b305e844
      Amir Goldstein authored
      We only need to encode origin if there is a chance that the same object was
      encoded pre copy up and then we need to stay consistent with the same
      encoding also after copy up.
      
      In case a non-pure upper is not indexed, then it was copied up before NFS
      export support was enabled. In that case, we don't need to worry about
      staying consistent with pre copy up encoding and we encode an upper file
      handle.
      
      This mitigates the problem that with no index, we cannot find an upper
      inode from origin inode, so we cannot decode a non-indexed upper from
      origin file handle.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      b305e844
    • Amir Goldstein's avatar
      ovl: decode connected upper dir file handles · 3985b70a
      Amir Goldstein authored
      Until this change, we decoded upper file handles by instantiating an
      overlay dentry from the real upper dentry. This is sufficient to handle
      pure upper files, but insufficient to handle merge/impure dirs.
      
      To that end, if decoded real upper dir is connected and hashed, we
      lookup an overlay dentry with the same path as the real upper dir.
      If decoded real upper is non-dir, we instantiate a disconnected overlay
      dentry as before this change.
      
      Because ovl_fh_to_dentry() returns a connected overlay dir dentry,
      exportfs never needs to call get_parent() and get_name() to reconnect an
      upper overlay dir. Because connectable non-dir file handles are not
      supported, exportfs will not be able to use fh_to_parent() and get_name()
      methods to reconnect a disconnected non-dir to its parent. Therefore, the
      methods get_parent() and get_name() are implemented just to print out a
      sanity warning and the method fh_to_parent() is implemented to warn the
      user that using the 'subtree_check' exportfs option is not supported.
      
      An alternative approach could have been to implement instantiating of
      an overlay directory inode from origin/index and implement get_parent()
      and get_name() by calling into underlying fs operations and them
      instantiating the overlay parent dir.
      
      The reasons for not choosing the get_parent() approach were:
      - Obtaining a disconnected overlay dir dentry would requires a
        delicate re-factoring of ovl_lookup() to get a dentry with overlay
        parent info. It was preferred to avoid doing that re-factoring unless
        it was proven worthy.
      - Going down the path of disconnected dir would mean that the (non
        trivial) code path of d_splice_alias() could be traveled and that
        meant writing more tests and introduces race cases that are very hard
        to hit on purpose. Taking the path of connecting overlay dentry by
        forward lookup is therefore the safe and boring way to avoid surprises.
      
      The culprits of the chosen "connected overlay dentry" approach:
      - We need to take special care to rename of ancestors while connecting
        the overlay dentry by real dentry path. These subtleties are usually
        handled by generic exportfs and VFS code.
      - In a hypothetical workload, we could end up in a loop trying to connect,
        interrupted by rename and restarting connect forever.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      3985b70a
    • Amir Goldstein's avatar
      ovl: decode pure upper file handles · 8556a420
      Amir Goldstein authored
      Decoding an upper file handle is done by decoding the upper dentry from
      underlying upper fs, finding or allocating an overlay inode that is
      hashed by the real upper inode and instantiating an overlay dentry with
      that inode.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      8556a420
    • Amir Goldstein's avatar
      ovl: encode pure upper file handles · 8ed5eec9
      Amir Goldstein authored
      Encode overlay file handles as struct ovl_fh containing the file handle
      encoding of the real upper inode.
      Signed-off-by: default avatarAmir Goldstein <amir73il@gmail.com>
      Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
      8ed5eec9