[OpenAFS-win32-devel] New client-side locking implementation

Eric Williams ericjw@citi.umich.edu
Wed, 27 Jul 2005 17:08:12 -0400 (EDT)


On Tue, 26 Jul 2005 asanka@secure-endpoints.com wrote:

> > > The interface to cm_Lock()/cm_Unlock will change in order
> > to support
> > > the notion of keyed locks.
> ...
> > IFS depends on locks being set on FileObjects (the kernel
> > result of an IRP_MJ_CREATE request), and being enforced on
> > the entire file. this only matters because of unlock_all and
> > unlock_by_key requests, which apply to the specified
> > FileObject, and not to all open instances of the file.
>
> The reason for the existence of IrpSp->Parameters.*.Key is to allow multiple
> "clients" to access an opened file.  Once IRP_MJ_CREATE is issued, and a
> file is opened, multiple processes can access the file using the same
> FileObject (inherited file handles).  Locking needs to be handled per
> process and per handle, or in other words, per client.
>
> Note that IRP_MJ_LOCK_CONTROL, IRP_MJ_READ, IRP_MJ_WRITE all use the key,
> which would be necessary to ensure that different clients using the same
> FileObject don't trample each other.
>
> The problem here is with handling IRP_MN_UNLOCK_ALL, which involves knowing
> all the locks that were obtained using a specific FileObject, and handling
> IRP_MN_UNLOCK_ALL_BY_KEY, which involves knowing all the locks that were
> obtained using a specific FileObject and Parameters.*.Key.  Handling this

it is my understanding that IRP_MN_UNLOCK_ALL is a request to remove all
locks on the specified FileObject that are also owned by the requesting
process.  page 713 of Nagar's book indicates this, and pg 714 further
indicates that only the owning process may remove locks.  there are
similar semantics for IRP_MN_UNLOCK_BY_KEY.

> situation wasn't a part of the design because the cm_Lock()/cm_Unlock()
> mechanism is not meant to deal with sets of locks; just one at a time.  This
> was supposed to be handled at the SMB or IFS layer.

it seems redundant to manually keep track of locks in the kernel for the
sole purpose of dispatching an appropriate number of unlock requests to
the daemon.  (however, see end.)

> For the SMB server, this isn't a problem because the SMB client keeps track
> of which locks were obtained and sends the proper SMB_COM_LOCKING_ANDX
> request to the server to unlock them (in fact, the SMB client does quite a
> bit more with the locks before any requests are generated for the SMB server
> to handle).  The SMB server code then goes through the list and calls
> cm_Unlock() for each lock to be unlocked(at least it will soon).  Other than
> that, the SMB server gets no notification akin to IRP_MN_UNLOCK_ALL or
> IRP_MN_UNLOCK_ALL_BY_KEY.
>
> If the IFS code doesn't keep track of locks in-kernel, we can extend the
> locking design on the cache manager to have two keys (whether they are
> actually two keys, or parts of the same key is an implementation matter), an
> InstanceKey and a ClientKey (which would be more clear than KeyA and KeyB).
> The InstanceKey can be unique for an instance of an open file (a file handle
> or SMB FID per session in SMB, or FileObject in IFS), while the ClientKey is
> unique per client per InstanceKey (a process in SMB, or a Parameters.*.Key
> for IFS).  We'll need to augment cm_Unlock() or provide a different call for
> unlocking based on just an InstanceKey or an InstanceKey,ClientKey pair.
>
> >
> > in fact, it would be possible to use a KeyA =
> > Key(FileObject).  the FileObject is unique -- across
> > processes, users, files.  making KeyA dependent on processID,
> > as i had earlier proposed, is redundant.
> >
> > > A key must consist of the SessionID, the ProcessID, and the
> > FID in order
> > > to provide uniqueness both for the file and the user.   The
> > SessionID is
> > >  irrelevant for the IFS because the ProcessID name space is unique.
> > > Therefore, for the IFS the SessionID can be set to a fixed
> > arbitrary
> > > value that will not be used by the CIFS/SMB interface.
> >
> > if the list of locks is stored in a queue attached to the
> > cm_scache_t, then i do not see why there exists a dependence
> > on the FID.
>
> The FID in question is the SMB file ID which represents an opened instance
> of the file, not the AFS FID.
>
> For SMB,
>   InstanceKey = I_Key(SessionID, FID)
>   ClientKey   = C_Key(ProcessID)
>
> For IFS,
>   InstanceKey = I_Key(IFS_MAGIC_SESSION_ID, I_ID(FileObject))
>   ClientKey   = C_Key(IrpSp->Parameters.*.Key)

again, i believe InstanceKey must be based on both the FileObject and the
processID.  an IRP_MN_UNLOCK_ALL will result in a remove-by-instance-key
call; this call should only unlock ranges owned by the process, not all
ranges on the FileObject.  this might be sent, for example, some time
after the last HANDLE is closed in a process (or when a process exits).


> ... If we are extending the CM to deal with batch unlocks.
>
>
> -- Asanka
>

all of this secondary-keying could be mitigated if the IFS version were to
manually inspect each locking request, compare it to known locks
(FsRtlGetNextFileLock), and then send the appropriate requests.  the trick
in this case would be to understand the request semantics properly so that
the lock lists would stay in sync.

eric