[OpenAFS-devel] Re: [OpenAFS] 2.6 kernel support anytime soon? Workarounds?

Jeffrey Hutzelman jhutz@cmu.edu
Mon, 10 May 2004 19:02:26 -0400


On Monday, May 10, 2004 18:01:17 -0400 Garrett Wollman 
<wollman@khavrinen.lcs.mit.edu> wrote:

> Putting the PAG in the supplementary group list, though unavoidable,
> was and is no less broken.

True.  But it's not terribly invasive and works pretty much everywhere.

> The semantics that AFS really wants (and
> probably kNFS/NFSv4 as well) are much closer to those of a process
> label.

Actually, the semantics that AFS really wants (and, I think, NFSv4 as well, 
but I'll let those people speak for themselves) are closest to those of a 
PAG.  That's no surprise -- what we want matches the concept we invented to 
do what we want.  It's possible that what we want maps well onto your 
favorite abstraction; it certainly maps reasonably well onto a variety of 
others.  It actually maps moderately well onto the supplementary group 
list, except that nasty AFS-unaware programs tend to come along and call 
setgroups() without regard to AFS.  Still, something better would be, well, 
better....

> What AFS wants are the following three functions:
>
> int afs_assign_process_label(afs_process_t p);
> int afs_get_label(afs_process_t p, afs_label_t *l);
> int afs_label_destruction_callback(afs_label_t l);

Not to be picky or anything, but those aren't functions; they're function 
declarations.  They tell me nothing whatsoever about what the functions 
actually _do_, let alone things that happen elsewhere in the system.

What AFS wants are setpag(), PagInCred(), and an inheritance model that 
matches our needs.  If I make some inferences about what the functions 
listed above do, and _if_ the inheritance model is correct, then yes, I can 
_almost_ build what AFS needs out of them:

typedef struct proc *afs_process_t;
typedef afs_uint32 afs_label_t;


int setpag(afs_uint32 pagvalue, afs_uint32 *newpag, int change_parent)
{
  int code;

  *newpag = (pagvalue == -1 ? genpag() : pagvalue);
  code = afs_assign_process_label(current, *newpag);
  if (code) return code;
  if (change_parent) {
    code = afs_assign_process_label(current->parent, *newpag);
    if (code) return code;
  }
  return 0;
}

// This is currently declared as follows:
// afs_int32 PagInCred(const struct AFS_UCRED *cred);


afs_uint32 PagInCred(const afs_process_t p)
{
  int code;
  afs_uint32 pagvalue;

  code = afs_get_label(p, &pagvalue);
  if (code) return NOPAG;
  return pagvalue;
}

int afs_label_destruction_callback(afs_label_t l)
{
  // whatever; it's just an integer
  return 0;
}


But note that it's not exact.  Your proposed afs_assign_process_label() 
doesn't actually provide a means to control what label is assigned.  And, 
afs_get_label() expects to operate on a process, where what we currently 
want is a struct ucred or whatever passes for it.  But then, that's 
platform-dependent code anyway, so it's not that big a deal.


The real difficulty is in the inheritance model.  We have a specific model:

(1) Every process has at most one PAG
(2) Processes start out with no PAG
(3) A new process inherits its parent's PAG, if any
(4) A process can request a new PAG for itself
(5) There is a funny operation that lets a process request a new PAG for
    itself _and its parent_.  I think this is evil, but it's there.
(6) A process never gets a new PAG except by (4) or (5).
(7) There is no way to go back to the PAG-less state.

We currently can get this by using the supplementary group list, except 
that we have to trap setgroups() in order to make (7) true.  Any new 
mechanism we use would have to have a very similar model.


-- Jeffrey T. Hutzelman (N3NHS) <jhutz+@cmu.edu>
   Sr. Research Systems Programmer
   School of Computer Science - Research Computing Facility
   Carnegie Mellon University - Pittsburgh, PA