22 Aug, 2014

1 commit


14 Aug, 2014

3 commits

  • There's no need to call locks_free_lock here while still holding the
    i_lock. Defer that until the lock has been dropped.

    Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • In commit 72f98e72551fa (locks: turn lock_flocks into a spinlock), we
    moved from using the BKL to a global spinlock. With this change, we lost
    the ability to block in the fl_release_private operation.

    This is problematic for NFS (and probably some other filesystems as
    well). Add a new list_head argument to locks_delete_lock. If that
    argument is non-NULL, then queue any locks that we want to free to the
    list instead of freeing them.

    Then, add a new locks_dispose_list function that will walk such a list
    and call locks_free_lock on them after the i_lock has been dropped.

    Finally, change all of the callers of locks_delete_lock to pass in a
    list_head, except for lease_modify. That function can be called long
    after the i_lock has been acquired. Deferring the freeing of a lease
    after unlocking it in that function is non-trivial until we overhaul
    some of the spinlocking in the lease code.

    Currently though, no filesystem that sets fl_release_private supports
    leases, so this is not currently a problem. We'll eventually want to
    make the same change in the lease code, but it needs a lot more work
    before we can reasonably do so.

    Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • Currently in the case where a new file lock completely replaces the old
    one, we end up overwriting the existing lock with the new info. This
    means that we have to call fl_release_private inside i_lock. Change the
    code to instead copy the info to new_fl, insert that lock into the
    correct spot and then delete the old lock. In a later patch, we'll defer
    the freeing of the old lock until after the i_lock has been dropped.

    Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     

12 Aug, 2014

2 commits


14 Jul, 2014

1 commit


11 Jun, 2014

1 commit

  • This fixes a regression due to commit 130d1f956ab3 (locks: ensure that
    fl_owner is always initialized properly in flock and lease codepaths). I
    had mistakenly thought that the fl_owner wasn't used in the lease code,
    but I missed the place in __break_lease that does use it.

    The i_have_this_lease check in generic_add_lease uses it. While I'm not
    sure that check is terribly helpful [1], reset it back to using
    current->files in order to ensure that there's no behavior change here.

    [1]: leases are owned by the file description. It's possible that this
    is a threaded program, and the lease breaker and the task that
    would handle the signal are different, even if they have the same
    file table. So, there is the potential for false positives with
    this check.

    Fixes: 130d1f956ab3 (locks: ensure that fl_owner is always initialized properly in flock and lease codepaths)
    Signed-off-by: Jeff Layton

    Jeff Layton
     

02 Jun, 2014

3 commits

  • v2: add a __break_lease tracepoint for non-blocking case

    Recently, I needed these to help track down a softlockup when recalling a
    delegation, but they might be helpful in other situations as well.

    Cc: "J. Bruce Fields"
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • Replace seq_printf where possible

    Cc: Jeff Layton
    Cc: Alexander Viro
    Cc: Andrew Morton
    Signed-off-by: Fabian Frederick
    Signed-off-by: Jeff Layton

    Fabian Frederick
     
  • Currently, the fl_owner isn't set for flock locks. Some filesystems use
    byte-range locks to simulate flock locks and there is a common idiom in
    those that does:

    fl->fl_owner = (fl_owner_t)filp;
    fl->fl_start = 0;
    fl->fl_end = OFFSET_MAX;

    Since flock locks are generally "owned" by the open file description,
    move this into the common flock lock setup code. The fl_start and fl_end
    fields are already set appropriately, so remove the unneeded setting of
    that in flock ops in those filesystems as well.

    Finally, the lease code also sets the fl_owner as if they were owned by
    the process and not the open file description. This is incorrect as
    leases have the same ownership semantics as flock locks. Set them the
    same way. The lease code doesn't actually use the fl_owner value for
    anything, so this is more for consistency's sake than a bugfix.

    Reported-by: Trond Myklebust
    Signed-off-by: Jeff Layton
    Acked-by: Greg Kroah-Hartman (Staging portion)
    Acked-by: J. Bruce Fields

    Jeff Layton
     

09 May, 2014

1 commit

  • v2: replace missing break in switch statement (as pointed out by Dave
    Jones)

    commit bce7560d4946 (locks: consolidate checks for compatible
    filp->f_mode values in setlk handlers) introduced a regression in the
    F_GETLK handler.

    flock64_to_posix_lock is a shared codepath between F_GETLK and F_SETLK,
    but the f_mode checks should only be applicable to the F_SETLK codepaths
    according to POSIX.

    Instead of just reverting the patch, add a new function to do this
    checking and have the F_SETLK handlers call it.

    Cc: Dave Jones
    Reported-and-Tested-by: Reuben Farrelly
    Signed-off-by: Jeff Layton

    Jeff Layton
     

24 Apr, 2014

1 commit


22 Apr, 2014

1 commit

  • File-private locks have been merged into Linux for v3.15, and *now*
    people are commenting that the name and macro definitions for the new
    file-private locks suck.

    ...and I can't even disagree. The names and command macros do suck.

    We're going to have to live with these for a long time, so it's
    important that we be happy with the names before we're stuck with them.
    The consensus on the lists so far is that they should be rechristened as
    "open file description locks".

    The name isn't a big deal for the kernel, but the command macros are not
    visually distinct enough from the traditional POSIX lock macros. The
    glibc and documentation folks are recommending that we change them to
    look like F_OFD_{GETLK|SETLK|SETLKW}. That lessens the chance that a
    programmer will typo one of the commands wrong, and also makes it easier
    to spot this difference when reading code.

    This patch makes the following changes that I think are necessary before
    v3.15 ships:

    1) rename the command macros to their new names. These end up in the uapi
    headers and so are part of the external-facing API. It turns out that
    glibc doesn't actually use the fcntl.h uapi header, but it's hard to
    be sure that something else won't. Changing it now is safest.

    2) make the the /proc/locks output display these as type "OFDLCK"

    Cc: Michael Kerrisk
    Cc: Christoph Hellwig
    Cc: Carlos O'Donell
    Cc: Stefan Metzmacher
    Cc: Andy Lutomirski
    Cc: Frank Filz
    Cc: Theodore Ts'o
    Signed-off-by: Jeff Layton

    Jeff Layton
     

15 Apr, 2014

1 commit

  • A fl->fl_break_time of 0 has a special meaning to the lease break code
    that basically means "never break the lease". knfsd uses this to ensure
    that leases don't disappear out from under it.

    Unfortunately, the code in __break_lease can end up passing this value
    to wait_event_interruptible as a timeout, which prevents it from going
    to sleep at all. This makes __break_lease to spin in a tight loop and
    causes soft lockups.

    Fix this by ensuring that we pass a minimum value of 1 as a timeout
    instead.

    Cc:
    Cc: J. Bruce Fields
    Reported-by: Terry Barnaby
    Signed-off-by: Jeff Layton

    Jeff Layton
     

31 Mar, 2014

16 commits

  • Allow locks_mandatory_area() to handle file-private locks correctly.
    If there is a file-private lock set on an open file and we're doing I/O
    via the same, then that should not cause anything to block.

    Handle this by first doing a non-blocking FL_ACCESS check for a
    file-private lock, and then fall back to checking for a classic POSIX
    lock (and possibly blocking).

    Note that this approach is subject to the same races that have always
    plagued mandatory locking on Linux.

    Reported-by: Trond Myklebust
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • As Trond pointed out, you can currently deadlock yourself by setting a
    file-private lock on a file that requires mandatory locking and then
    trying to do I/O on it.

    Avoid this problem by plumbing some knowledge of file-private locks into
    the mandatory locking code. In order to do this, we must pass down
    information about the struct file that's being used to
    locks_verify_locked.

    Reported-by: Trond Myklebust
    Signed-off-by: Jeff Layton
    Acked-by: J. Bruce Fields

    Jeff Layton
     
  • Neil Brown suggested potentially overloading the l_pid value as a "lock
    context" field for file-private locks. While I don't think we will
    probably want to do that here, it's probably a good idea to ensure that
    in the future we could extend this API without breaking existing
    callers.

    Typically the l_pid value is ignored for incoming struct flock
    arguments, serving mainly as a place to return the pid of the owner if
    there is a conflicting lock. For file-private locks, require that it
    currently be set to 0 and return EINVAL if it isn't. If we eventually
    want to make a non-zero l_pid mean something, then this will help ensure
    that we don't break legacy programs that are using file-private locks.

    Cc: Neil Brown
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • Due to some unfortunate history, POSIX locks have very strange and
    unhelpful semantics. The thing that usually catches people by surprise
    is that they are dropped whenever the process closes any file descriptor
    associated with the inode.

    This is extremely problematic for people developing file servers that
    need to implement byte-range locks. Developers often need a "lock
    management" facility to ensure that file descriptors are not closed
    until all of the locks associated with the inode are finished.

    Additionally, "classic" POSIX locks are owned by the process. Locks
    taken between threads within the same process won't conflict with one
    another, which renders them useless for synchronization between threads.

    This patchset adds a new type of lock that attempts to address these
    issues. These locks conflict with classic POSIX read/write locks, but
    have semantics that are more like BSD locks with respect to inheritance
    and behavior on close.

    This is implemented primarily by changing how fl_owner field is set for
    these locks. Instead of having them owned by the files_struct of the
    process, they are instead owned by the filp on which they were acquired.
    Thus, they are inherited across fork() and are only released when the
    last reference to a filp is put.

    These new semantics prevent them from being merged with classic POSIX
    locks, even if they are acquired by the same process. These locks will
    also conflict with classic POSIX locks even if they are acquired by
    the same process or on the same file descriptor.

    The new locks are managed using a new set of cmd values to the fcntl()
    syscall. The initial implementation of this converts these values to
    "classic" cmd values at a fairly high level, and the details are not
    exposed to the underlying filesystem. We may eventually want to push
    this handing out to the lower filesystem code but for now I don't
    see any need for it.

    Also, note that with this implementation the new cmd values are only
    available via fcntl64() on 32-bit arches. There's little need to
    add support for legacy apps on a new interface like this.

    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • It's not really feasible to do deadlock detection with FL_FILE_PVT
    locks since they aren't owned by a single task, per-se. Deadlock
    detection also tends to be rather expensive so just skip it for
    these sorts of locks.

    Also, add a FIXME comment about adding more limited deadlock detection
    that just applies to ro -> rw upgrades, per Andy's request.

    Cc: Andy Lutomirski
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • Once we introduce file private locks, we'll need to know what cmd value
    was used, as that affects the ownership and whether a conflict would
    arise.

    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • FL_FILE_PVT locks are no longer tied to a particular pid, and are
    instead inheritable by child processes. Report a l_pid of '-1' for
    these sorts of locks since the pid is somewhat meaningless for them.

    This precedent comes from FreeBSD. There, POSIX and flock() locks can
    conflict with one another. If fcntl(F_GETLK, ...) returns a lock set
    with flock() then the l_pid member cannot be a process ID because the
    lock is not held by a process as such.

    Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • In a later patch, we'll be adding a new type of lock that's owned by
    the struct file instead of the files_struct. Those sorts of locks
    will be flagged with a new FL_FILE_PVT flag.

    Report these types of locks as "FLPVT" in /proc/locks to distinguish
    them from "classic" POSIX locks.

    Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • This function currently removes leases in addition to flock locks and in
    a later patch we'll have it deal with file-private locks too. Rename it
    to locks_remove_file to indicate that it removes locks that are
    associated with a particular struct file, and not just flock locks.

    Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • Move this check into flock64_to_posix_lock instead of duplicating it in
    two places. This also fixes a minor wart in the code where we continue
    referring to the struct flock after converting it to struct file_lock.

    Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • In the 32-bit case fcntl assigns the 64-bit f_pos and i_size to a 32-bit
    off_t.

    The existing range checks also seem to depend on signed arithmetic
    wrapping when it overflows. In practice maybe that works, but we can be
    more careful. That also allows us to make a more reliable distinction
    between -EINVAL and -EOVERFLOW.

    Note that in the 32-bit case SEEK_CUR or SEEK_END might allow the caller
    to set a lock with starting point no longer representable as a 32-bit
    value. We could return -EOVERFLOW in such cases, but the locks code is
    capable of handling such ranges, so we choose to be lenient here. The
    only problem is that subsequent GETLK calls on such a lock will fail
    with EOVERFLOW.

    While we're here, do some cleanup including consolidating code for the
    flock and flock64 cases.

    Signed-off-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    J. Bruce Fields
     
  • A leftover lock on the list is surely a sign of a problem of some sort,
    but it's not necessarily a reason to panic the box. Instead, just log a
    warning with some info about the lock, and then delete it like we would
    any other lock.

    In the event that the filesystem declares a ->lock f_op, we may end up
    leaking something, but that's generally preferable to an immediate
    panic.

    Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • ...to make sparse happy.

    Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • It's best to let the compiler decide that.

    Acked-by: J. Bruce Fields
    Reported-by: Stephen Rothwell
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • Acked-by: J. Bruce Fields
    Signed-off-by: Jeff Layton

    Jeff Layton
     
  • As Al Viro points out, there is an unlikely, but possible race between
    opening a file and setting a lease on it. generic_add_lease is done with
    the i_lock held, but the inode->i_flock check in break_lease is
    lockless. It's possible for another task doing an open to do the entire
    pathwalk and call break_lease between the point where generic_add_lease
    checks for a conflicting open and adds the lease to the list. If this
    occurs, we can end up with a lease set on the file with a conflicting
    open.

    To guard against that, check again for a conflicting open after adding
    the lease to the i_flock list. If the above race occurs, then we can
    simply unwind the lease setting and return -EAGAIN.

    Because we take dentry references and acquire write access on the file
    before calling break_lease, we know that if the i_flock list is empty
    when the open caller goes to check it then the necessary refcounts have
    already been incremented. Thus the additional check for a conflicting
    open will see that there is one and the setlease call will fail.

    Cc: Bruce Fields
    Cc: David Howells
    Cc: "Paul E. McKenney"
    Reported-by: Al Viro
    Signed-off-by: Jeff Layton
    Signed-off-by: J. Bruce Fields

    Jeff Layton
     

13 Nov, 2013

1 commit


09 Nov, 2013

2 commits

  • Implement NFSv4 delegations at the vfs level using the new FL_DELEG lock
    type.

    Note nfsd is the only delegation user and is only using read
    delegations. Warn on any attempt to set a write delegation for now.
    We'll come back to that case later.

    Acked-by: Jeff Layton
    Signed-off-by: J. Bruce Fields
    Signed-off-by: Al Viro

    J. Bruce Fields
     
  • For now FL_DELEG is just a synonym for FL_LEASE. So this patch doesn't
    change behavior.

    Next we'll modify break_lease to treat FL_DELEG leases differently, to
    account for the fact that NFSv4 delegations should be broken in more
    situations than Windows oplocks.

    Acked-by: Jeff Layton
    Signed-off-by: J. Bruce Fields
    Signed-off-by: Al Viro

    J. Bruce Fields
     

25 Oct, 2013

1 commit


08 Jul, 2013

1 commit

  • The file_lock_list is only used for /proc/locks. The vastly common case
    is for locks to be put onto the list and come off again, without ever
    being traversed.

    Help optimize for this use-case by moving to percpu hlist_head-s. At the
    same time, we can make the locking less contentious by moving to an
    lglock. When iterating over the lists for /proc/locks, we must take the
    global lock and then iterate over each CPU's list in turn.

    This change necessitates a new fl_link_cpu field to keep track of which
    CPU the entry is on. On x86_64 at least, this field is placed within an
    existing hole in the struct to avoid growing the size.

    Signed-off-by: Jeff Layton
    Acked-by: J. Bruce Fields
    Signed-off-by: Al Viro

    Jeff Layton
     

05 Jul, 2013

1 commit


29 Jun, 2013

3 commits

  • There's no reason we have to protect the blocked_hash and file_lock_list
    with the same spinlock. With the tests I have, breaking it in two gives
    a barely measurable performance benefit, but it seems reasonable to make
    this locking as granular as possible.

    Signed-off-by: Jeff Layton
    Signed-off-by: Al Viro

    Jeff Layton
     
  • Currently, the hashing that the locking code uses to add these values
    to the blocked_hash is simply calculated using fl_owner field. That's
    valid in most cases except for server-side lockd, which validates the
    owner of a lock based on fl_owner and fl_pid.

    In the case where you have a small number of NFS clients doing a lot
    of locking between different processes, you could end up with all
    the blocked requests sitting in a very small number of hash buckets.

    Add a new lm_owner_key operation to the lock_manager_operations that
    will generate an unsigned long to use as the key in the hashtable.
    That function is only implemented for server-side lockd, and simply
    XORs the fl_owner and fl_pid.

    Signed-off-by: Jeff Layton
    Acked-by: J. Bruce Fields
    Signed-off-by: Al Viro

    Jeff Layton
     
  • Break up the blocked_list into a hashtable, using the fl_owner as a key.
    This speeds up searching the hash chains, which is especially significant
    for deadlock detection.

    Note that the initial implementation assumes that hashing on fl_owner is
    sufficient. In most cases it should be, with the notable exception being
    server-side lockd, which compares ownership using a tuple of the
    nlm_host and the pid sent in the lock request. So, this may degrade to a
    single hash bucket when you only have a single NFS client. That will be
    addressed in a later patch.

    The careful observer may note that this patch leaves the file_lock_list
    alone. There's much less of a case for turning the file_lock_list into a
    hashtable. The only user of that list is the code that generates
    /proc/locks, and it always walks the entire list.

    Signed-off-by: Jeff Layton
    Acked-by: J. Bruce Fields
    Signed-off-by: Al Viro

    Jeff Layton