• D
    Introduce an internal API for handling file based lockspaces · eca72d47
    Daniel P. Berrange 提交于
    The previously introduced virFile{Lock,Unlock} APIs provide a
    way to acquire/release fcntl() locks on individual files. For
    unknown reason though, the POSIX spec says that fcntl() locks
    are released when *any* file handle referring to the same path
    is closed. In the following sequence
    
      threadA: fd1 = open("foo")
      threadB: fd2 = open("foo")
      threadA: virFileLock(fd1)
      threadB: virFileLock(fd2)
      threadB: close(fd2)
    
    you'd expect threadA to come out holding a lock on 'foo', and
    indeed it does hold a lock for a very short time. Unfortunately
    when threadB does close(fd2) this releases the lock associated
    with fd1. For the current libvirt use case for virFileLock -
    pidfiles - this doesn't matter since the lock is acquired
    at startup while single threaded an never released until
    exit.
    
    To provide a more generally useful API though, it is necessary
    to introduce a slightly higher level abstraction, which is to
    be referred to as a "lockspace".  This is to be provided by
    a virLockSpacePtr object in src/util/virlockspace.{c,h}. The
    core idea is that the lockspace keeps track of what files are
    already open+locked. This means that when a 2nd thread comes
    along and tries to acquire a lock, it doesn't end up opening
    and closing a new FD. The lockspace just checks the current
    list of held locks and immediately returns VIR_ERR_RESOURCE_BUSY.
    
    NB, the API as it stands is designed on the basis that the
    files being locked are not being otherwise opened and used
    by the application code. One approach to using this API is to
    acquire locks based on a hash of the filepath.
    
    eg to lock /var/lib/libvirt/images/foo.img the application
    might do
    
       virLockSpacePtr lockspace = virLockSpaceNew("/var/lib/libvirt/imagelocks");
       lockname = md5sum("/var/lib/libvirt/images/foo.img");
       virLockSpaceAcquireLock(lockspace, lockname);
    
    NB, in this example, the caller should ensure that the path
    is canonicalized before calculating the checksum.
    
    It is also possible to do locks directly on resources by
    using a NULL lockspace directory and then using the file
    path as the lock name eg
    
       virLockSpacePtr lockspace = virLockSpaceNew(NULL);
       virLockSpaceAcquireLock(lockspace, "/var/lib/libvirt/images/foo.img");
    
    This is only safe to do though if no other part of the process
    will be opening the files. This will be the case when this
    code is used inside the soon-to-be-reposted virlockd daemon
    Signed-off-by: NDaniel P. Berrange <berrange@redhat.com>
    eca72d47
.gitignore 3.5 KB