17 Jun, 2020

1 commit

  • 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: e49c7b2f6de7 ("afs: Build an abstraction around an "operation" concept")
    Reported-by: Marc Dionne
    Signed-off-by: David Howells

    David Howells
     

16 Jun, 2020

1 commit

  • afs_check_for_remote_deletion() checks to see if error ENOENT is returned
    by the server in response to an operation and, if so, marks the primary
    vnode as having been deleted as the FID is no longer valid.

    However, it's being called from the operation success functions, where no
    abort has happened - and if an inline abort is recorded, it's handled by
    afs_vnode_commit_status().

    Fix this by actually calling the operation aborted method if provided and
    having that point to afs_check_for_remote_deletion().

    Fixes: e49c7b2f6de7 ("afs: Build an abstraction around an "operation" concept")
    Signed-off-by: David Howells

    David Howells
     

04 Jun, 2020

1 commit

  • Turn the afs_operation struct into the main way that most fileserver
    operations are managed. Various things are added to the struct, including
    the following:

    (1) All the parameters and results of the relevant operations are moved
    into it, removing corresponding fields from the afs_call struct.
    afs_call gets a pointer to the op.

    (2) The target volume is made the main focus of the operation, rather than
    the target vnode(s), and a bunch of op->vnode->volume are made
    op->volume instead.

    (3) Two vnode records are defined (op->file[]) for the vnode(s) involved
    in most operations. The vnode record (struct afs_vnode_param)
    contains:

    - The vnode pointer.

    - The fid of the vnode to be included in the parameters or that was
    returned in the reply (eg. FS.MakeDir).

    - The status and callback information that may be returned in the
    reply about the vnode.

    - Callback break and data version tracking for detecting
    simultaneous third-parth changes.

    (4) Pointers to dentries to be updated with new inodes.

    (5) An operations table pointer. The table includes pointers to functions
    for issuing AFS and YFS-variant RPCs, handling the success and abort
    of an operation and handling post-I/O-lock local editing of a
    directory.

    To make this work, the following function restructuring is made:

    (A) The rotation loop that issues calls to fileservers that can be found
    in each function that wants to issue an RPC (such as afs_mkdir()) is
    extracted out into common code, in a new file called fs_operation.c.

    (B) The rotation loops, such as the one in afs_mkdir(), are replaced with
    a much smaller piece of code that allocates an operation, sets the
    parameters and then calls out to the common code to do the actual
    work.

    (C) The code for handling the success and failure of an operation are
    moved into operation functions (as (5) above) and these are called
    from the core code at appropriate times.

    (D) The pseudo inode getting stuff used by the dynamic root code is moved
    over into dynroot.c.

    (E) struct afs_iget_data is absorbed into the operation struct and
    afs_iget() expects to be given an op pointer and a vnode record.

    (F) Point (E) doesn't work for the root dir of a volume, but we know the
    FID in advance (it's always vnode 1, unique 1), so a separate inode
    getter, afs_root_iget(), is provided to special-case that.

    (G) The inode status init/update functions now also take an op and a vnode
    record.

    (H) The RPC marshalling functions now, for the most part, just take an
    afs_operation struct as their only argument. All the data they need
    is held there. The result delivery functions write their answers
    there as well.

    (I) The call is attached to the operation and then the operation core does
    the waiting.

    And then the new operation code is, for the moment, made to just initialise
    the operation, get the appropriate vnode I/O locks and do the same rotation
    loop as before.

    This lays the foundation for the following changes in the future:

    (*) Overhauling the rotation (again).

    (*) Support for asynchronous I/O, where the fileserver rotation must be
    done asynchronously also.

    Signed-off-by: David Howells

    David Howells
     

31 May, 2020

1 commit


13 Apr, 2020

1 commit

  • AFS directories are retained locally as a structured file, with lookup
    being effected by a local search of the file contents. When a modification
    (such as mkdir) happens, the dir file content is modified locally rather
    than redownloading the directory.

    The directory contents are accessed in a number of ways, with a number of
    different locks schemes:

    (1) Download of contents - dvnode->validate_lock/write in afs_read_dir().

    (2) Lookup and readdir - dvnode->validate_lock/read in afs_dir_iterate(),
    downgrading from (1) if necessary.

    (3) d_revalidate of child dentry - dvnode->validate_lock/read in
    afs_do_lookup_one() downgrading from (1) if necessary.

    (4) Edit of dir after modification - page locks on individual dir pages.

    Unfortunately, because (4) uses different locking scheme to (1) - (3),
    nothing protects against the page being scanned whilst the edit is
    underway. Even download is not safe as it doesn't lock the pages - relying
    instead on the validate_lock to serialise as a whole (the theory being that
    directory contents are treated as a block and always downloaded as a
    block).

    Fix this by write-locking dvnode->validate_lock around the edits. Care
    must be taken in the rename case as there may be two different dirs - but
    they need not be locked at the same time. In any case, once the lock is
    taken, the directory version must be rechecked, and the edit skipped if a
    later version has been downloaded by revalidation (there can't have been
    any local changes because the VFS holds the inode lock, but there can have
    been remote changes).

    Fixes: 63a4681ff39c ("afs: Locally edit directory data for mkdir/create/unlink/...")
    Signed-off-by: David Howells

    David Howells
     

20 Jun, 2019

1 commit

  • d_delete() was piggy backed for the fsnotify_nameremove() hook when
    in fact not all callers of d_delete() care about fsnotify events.

    For all callers of d_delete() that may be interested in fsnotify events,
    we made sure to call one of fsnotify_{unlink,rmdir}() hooks before
    calling d_delete().

    Now we can move the fsnotify_nameremove() call from d_delete() to the
    fsnotify_{unlink,rmdir}() hooks.

    Two explicit calls to fsnotify_nameremove() from nfs/afs sillyrename
    are also removed. This will cause a change of behavior - nfs/afs will
    NOT generate an fsnotify delete event when renaming over a positive
    dentry. This change is desirable, because it is consistent with the
    behavior of all other filesystems.

    Signed-off-by: Amir Goldstein
    Signed-off-by: Jan Kara

    Amir Goldstein
     

24 May, 2019

1 commit

  • Based on 1 normalized pattern(s):

    this program is free software you can redistribute it and or modify
    it under the terms of the gnu general public licence as published by
    the free software foundation either version 2 of the licence or at
    your option any later version

    extracted by the scancode license scanner the SPDX license identifier

    GPL-2.0-or-later

    has been chosen to replace the boilerplate/reference in 114 file(s).

    Signed-off-by: Thomas Gleixner
    Reviewed-by: Allison Randal
    Reviewed-by: Kate Stewart
    Cc: linux-spdx@vger.kernel.org
    Link: https://lkml.kernel.org/r/20190520170857.552531963@linutronix.de
    Signed-off-by: Greg Kroah-Hartman

    Thomas Gleixner
     

16 May, 2019

2 commits

  • When applying the status and callback in the response of an operation,
    apply them in the same critical section so that there's no race between
    checking the callback state and checking status-dependent state (such as
    the data version).

    Fix this by:

    (1) Allocating a joint {status,callback} record (afs_status_cb) before
    calling the RPC function for each vnode for which the RPC reply
    contains a status or a status plus a callback. A flag is set in the
    record to indicate if a callback was actually received.

    (2) These records are passed into the RPC functions to be filled in. The
    afs_decode_status() and yfs_decode_status() functions are removed and
    the cb_lock is no longer taken.

    (3) xdr_decode_AFSFetchStatus() and xdr_decode_YFSFetchStatus() no longer
    update the vnode.

    (4) xdr_decode_AFSCallBack() and xdr_decode_YFSCallBack() no longer update
    the vnode.

    (5) vnodes, expected data-version numbers and callback break counters
    (cb_break) no longer need to be passed to the reply delivery
    functions.

    Note that, for the moment, the file locking functions still need
    access to both the call and the vnode at the same time.

    (6) afs_vnode_commit_status() is now given the cb_break value and the
    expected data_version and the task of applying the status and the
    callback to the vnode are now done here.

    This is done under a single taking of vnode->cb_lock.

    (7) afs_pages_written_back() is now called by afs_store_data() rather than
    by the reply delivery function.

    afs_pages_written_back() has been moved to before the call point and
    is now given the first and last page numbers rather than a pointer to
    the call.

    (8) The indicator from YFS.RemoveFile2 as to whether the target file
    actually got removed (status.abort_code == VNOVNODE) rather than
    merely dropping a link is now checked in afs_unlink rather than in
    xdr_decode_YFSFetchStatus().

    Supplementary fixes:

    (*) afs_cache_permit() now gets the caller_access mask from the
    afs_status_cb object rather than picking it out of the vnode's status
    record. afs_fetch_status() returns caller_access through its argument
    list for this purpose also.

    (*) afs_inode_init_from_status() now uses a write lock on cb_lock rather
    than a read lock and now sets the callback inside the same critical
    section.

    Fixes: c435ee34551e ("afs: Overhaul the callback handling")
    Signed-off-by: David Howells

    David Howells
     
  • Make certain RPC operations non-interruptible, including:

    (*) Set attributes
    (*) Store data

    We don't want to get interrupted during a flush on close, flush on
    unlock, writeback or an inode update, leaving us in a state where we
    still need to do the writeback or update.

    (*) Extend lock
    (*) Release lock

    We don't want to get lock extension interrupted as the file locks on
    the server are time-limited. Interruption during lock release is less
    of an issue since the lock is time-limited, but it's better to
    complete the release to avoid a several-minute wait to recover it.

    *Setting* the lock isn't a problem if it's interrupted since we can
    just return to the user and tell them they were interrupted - at
    which point they can elect to retry.

    (*) Silly unlink

    We want to remove silly unlink files if we can, rather than leaving
    them for the salvager to clear up.

    Note that whilst these calls are no longer interruptible, they do have
    timeouts on them, so if the server stops responding the call will fail with
    something like ETIME or ECONNRESET.

    Without this, the following:

    kAFS: Unexpected error from FS.StoreData -512

    appears in dmesg when a pending store data gets interrupted and some
    processes may just hang.

    Additionally, make the code that checks/updates the server record ignore
    failure due to interruption if the main call is uninterruptible and if the
    server has an address list. The next op will check it again since the
    expiration time on the old list has past.

    Fixes: d2ddc776a458 ("afs: Overhaul volume and server record caching and fileserver rotation")
    Reported-by: Jonathan Billings
    Reported-by: Marc Dionne
    Signed-off-by: David Howells

    David Howells
     

25 Apr, 2019

1 commit

  • 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: David Howells

    David Howells