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

asanka@secure-endpoints.com asanka@secure-endpoints.com
Tue, 26 Jul 2005 18:27:35 -0400


> the FsRtl library has two hooks for lock operations.  when a 
> lock is placed, the hook is then called and has veto power.  
> when a lock is removed, the second hook is called.  these are 
> meant specifically for network redirector use.  given the 
> semantics discussed, calling cm_Lock/cm_Unlock from these 
> hooks seems to be a good solution.

Yes.

> > 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
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.

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)

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


-- Asanka