Peter Memishian wrote:
> > For the Link ID management API:
> >
> > dladm_create_linkid() /* get_new_linkid */
> > dladm_destroy_linkid() /* delete_linkid */
> > dladm_linkid2name() /* id2name */
> > dladm_name2linkid() /* name2id */
> > dladm_change_linkid_mapping() /* rename */
> > dladm_walk_linkid() /* The walker mentioned in my reply to Cathy */
> >
> > For the persistent link configuration API:
> >
> > dladm_create_conf() /* get_new_conf */
> > dladm_set_conf_field() /* set_conf_field */
> > dladm_get_conf_field() /* get_conf_field */
> > dladm_read_conf() /* get_conf */
> > dladm_write_conf() /* commit_conf */
> > dladm_delete_conf() /* delete_conf */
> > dladm_destroy_conf() /* free_conf */
> > dladm_walk_conf() /* walk_confs */
>
> I like those names -- except dladm_change_linkid_mapping(), which feels
> a bit bulky. Maybe:
>
> dladm_status_t dladm_remap_linkid(dladm_linkid_t id, const char *linkname)
>
OK, sounds good.
Also, I noticed the other mails between you and Cathy about the
dladm_delete_conf and dladm_destroy_conf names. Let's rename
dladm_delete_conf dladm_remove_conf.
> > I'd prefer to not require class, ID, and name for the create call,
> > because what if in the future we need more required fields in the
> > future, but I see your point.
>
> Do you have any other specific required fields in mind? Or is more of a
> future-proofing of the API?
>
It is more future proofing. How about I do something like:
dladm_create_conf(const char *name, const char *class, dladm_linkid_t
id, dladm_conf_t *conf, void *args);
Where args is marked for future growth?
> > I'll also make the ID and class field read-only so that attempts to set
> > either with dladm_set_conf_field will fail.
>
> Sounds good.
>
> > > Why couldn't that be detected when the persistence is attempted -- e.g.,
> > > fail the commit/write()?
> >
> > I could add some checks. We could have the commit check to make sure
> > the name to ID mapping in the configuration structure matches what the
> > link ID management API shows. However, I'm not sure how the
> > configuration API would tell the difference between this situation and a
> > rename operation.
> >
> > For example, we search using an ID to see if there is already an
> > existing persistent configuration for this ID. Since net10 has net6's
> > ID, there is a configuration. We can tell the names are different, but
> > how does the API tell the difference between this operation and an
> > attempt to rename the interface?
>
> My thinking was that the API should never allow a configuration to be
> written out that would result in two persisted configurations with the
> same linkid. In the scenario you gave before:
>
> delete_linkid("net6");
> id = get_new_linkid("net10", class); /* Could return net6's link ID! */
> create_conf("net10", id, ...)
> write_conf("net10");
>
> ... the write_conf() for "net10" would fail because "net6" already has
> its persistent linkid. If someone wanted to do a rename, they'd need to
> delete_conf("net6") first.
>
We could do this. This does make renaming a little more complicated
since there's a particular order things have to happen. If we went this
route I would want to add Cathy's suggested conf_rename function, and we
might also want to make name a read only field of the configuration.
> > Another problem I thought of as I typed this up is what happens if
> > devfsadmd crashes and is restarted? Then we lose all the temporary link
> > ID to name mappings, unless devfsadmd has some way of storing the
> > temporary link ID to name mappings. If we persist them with the
> > persistence API, the mapping is restored on reboot, which is not what
> > we'd want.
> >
> > I think my use of the term persistence could be problematic elsewhere.
>
> This is certainly something worth some thought, but my gut reaction is
> that recovery of temporary state across it crashing is no more a
> requirement than recovery of temporary state across a kernel crash.
>
I think we might have situations where we would have undesirable
behavior. I'd need to think about this. Do you think this problem
should be solved before we continue? I think what we have is pretty
high level, and we can begin work on the internals.
> > Even if we have two processes (or even two threads in the same process)
> > trying to change the same link's configuration?
>
> There are two separate notions of safety here. One is that the
> configuration is self-consistent and not corrupt. That is, the API must
> not allow a given persistent configuration to appear to be a mongrel
> consisting of state that was written by multiple threads competing to
> update it. That is, from the point of view of a thread using the API to
> read the persistent configuration, it should always see a single,
> consistent view of the persistent configuration.
>
OK, agreed.
> The other notion of safety is to protect against update collisions (i.e.,
> from multiple updaters stomping on one-another) -- e.g., one application
> tries to name a link one thing, and the other tries to name a link another
> thing. I think as long as the resulting configuration is self-consistent
> (that is, the final link name reflects either one name or the other), this
> is not required.
>
> That said, I *think* we'd need to make some changes to the API to satisfy
> the first notion of safety. Specifically, since some changes require
> atomically applying changes to several links (e.g., creating an
> aggregation with two links), I think read_conf()/write_conf() would need
> to operate on the entire persistent configuration, rather than just a
> given link. With that approach, I think it would also be possible to
> detect/prevent update collisions -- e.g., you could store a generation
> number associated with the configuration that is returned when it is read,
> and then bump that number when it's written out. If the number doesn't
> match across the read()/write(), then the writer is forced to go re-read
> to pull in the latest changes (and generation number), and then retry the
> write() if appropriate.
>
I see what you're saying. I think it would work, and I think we could
hide the details of how it worked, and the only API change would be a
new error value. Let me think about that.
Dan