Re: To Unmount Or Not To Unmount

Ingo Weinhold <bonefish-CFLBMwTPW48UNGrzBIF7/[email protected]> Fri, 26 Sep 2003 21:40:38 +0200
Newsgroups gmane.os.openbeos.storage
Message-ID <[email protected]>
On 2003-09-26 at 08:26:47 [+0200], Tyler Dauwalder wrote:
> On 2003-09-23 at 14:09:44 [-0700], Ingo Weinhold wrote:
> > On 2003-09-23 at 20:38:24 [+0200], Axel D=F6rfler wrote:
[...]
> > > That's what I thought, too... that's what the integration with the =
VFS
> > > is all about, right?
> >=20
> > I should clarify the situations that can occur:
> >=20
> > 1) Partition is busy: There are scheduled or already executing jobs, =
that
> > affect the partition. Jobs are scheduled, when
> > BDiskDevice::CommitModifications() is invoked.
> >=20
> > 2) A user has invoked BDiskDevice::PrepareModifications() (started a
> > transaction, to use that term) but not yet called
> > BDiskDevice::{Cancel,Commit}Modifications() (rolled back respectively
> > committed the transaction).
> > a) Mount()/Unmount() is invoked on a BPartition object belonging to t=
he
> > very same BDiskDevice object.
> > b) Mount()/Unmount() is invoked on a BPartition object belonging to=20
> > another
> > user (but of course referring to the same partition).
> > c) mount()/unmount() is invoked for the partition.
> >=20
> > There's no further distinction of cases for 1), because in any case, =
the
> > same must happen: mount(), unmount(), Mount(), Unmount() must fail, f=
or
> > otherwise we'd risk, that something bad will happen, if the mount sta=
te
> > changes behind the back of a job that operates on that partition.
> >=20
> > What shall happen in the case 2)a)-c) was subject of my mail. :-)
>=20
> I really did understand that, even if it perhaps didn't seem like it. :=
-)
> When you said, "On the other hand, mounting/unmounting can be done by a
> third party at any time, even if one is preparing modifications at that
> time", it just sounded as though you were implying a call to mount() or
> unmount() could go and do things behind the back of the ddm. That being
> said, having the cases enumerated is useful. :-)

Ah, OK, then I misunderstood you.

> > > > This seems like an
> > > > (almost :-) reasonable restriction to me: once you start planning=
 a=20
> > > > set
> > > > of jobs that involve a partition, you can't mount/unmount it unti=
l you
> > > > cancel or no more
> > > > jobs remain that affect that partition.
> >=20
> > Please don't mix that up. Until you commit the changes you're in the
> > situation 2) (and there aren't any jobs yet), that is, in principle,
> > there'd be no problem with mounting/unmounting immediately. At least =
from
> > the DDM point of view.
>=20
> No, I wasn't mixed up (at least, I don't think I was :-). I was saying =
it
> would seem reasonable to me to disallow mounting and unmounting anythin=
g on
> a device from the time PrepareModifications() was called on a device un=
til
> no shadow partitions were left for it, and then disallow mounting and
> unmounting any busy partitions as long as they were still marked busy, =
just
> as is implied by the suggestion below that Mount() and Unmount() call
> PrepareModifications() on their own as needed.

I see. That's rather restrictive, but would be the easiest to implement=20
variant, I believe. Though, unless there are significant differences in=20
complexity of the different possible handlings, I think, that shouldn't b=
e a=20
criterion to affect the decision for or against any one.

> > > > We could add an appropriate
> > > > error
> > > > code so we could give a reasonable error message in Tracker and
> > > > mount()/unmount(), suggesting that "The partition is locked, perh=
aps
> > > > you're
> > > > mucking around with things in DriveSetup?" similar to the busy
> > > > message you
> > > > get when you try to unmount a CD you're currently playing in
> > > > SoundPlay. The
> > > > only problem I see with this so far is that it does seems better =
to
> > > > allow a
> > > > partition to be unmounted even if jobs are being prepared for it,=
 but
> > > > perhaps this would be justification for a hybrid approach with
> > > > Unmount() as
> > > > addressed below.
> > >=20
> > > Not sure about that - the jobs in question should know about the dr=
ive
> > > status; I could imagine that their operation is different when the =
disk
> > > is mounted vs. unmounted.
> > > Maybe we should think about that deeply, first, too :-)
> >=20
> > Well, as far as the jobs go, there are no choices. As soon as they ar=
e
> > created, the partitions that are going to be affected are marked busy=
 and
> > mounting/unmounting and modification requests must fail.
> > That point is, that the jobs are only created when the modifications =
are
> > committed. Until then, we are free to mount/unmount would-be affected
> > partitions.
>=20
> I think his point was that, for example, whoever is responsible for res=
izing
> the bfs partition is likely going to want to know whether the partition=
 is
> mounted or not, assuming resizing while mounted is supported.

Maybe my understanding suffered a bit from too much alcohol or sleep=20
deprivation, but I can't see, where the problem is suspected. Of course=20
anyone involved in the process can check the status of the device/partiti=
on.=20
For the disk system modules it is available through=20
{disk_device,partition}_data structures (either passed directly to the=20
respective hook or gettable via the exported DDM C functions), for the jo=
bs=20
and the rest of the DDM code KDiskDevice/KPartition hold that info, and -=
-=20
though not first hand -- in userland the BDiskDevice/BPartition classes=20
provide it.

[...]
> > > > > Oh, there's still the general question whether the user has to
> > > > > Unmount()
> > > > > the concerned partition explicitely, when e.g. CanResize()
> > > > > reported, that
> > > > > it works only when the partition is unmounted, or whether Resiz=
e()
> > > > > would
> > > > > automagically do the unmounting (or at least mark the partition=
 to
> > > > > be
> > > > > unmounted).
> > > > Perhaps an unmount call should just be placed in from of the
> > > > offending job
> > > > in the job queue when it's built.
> >=20
> > What I was thinking of, was, that when a job gets executed, it would=20
> > itself
> > first invoke the respective Validate*() hooks of the disk system agai=
n and
> > learn, if the disk system needs a currently mounted partition unmount=
ed,=20
> > or
> > if something's fishy and it should rather fail on the spot.
> >=20
> > So, if it realizes that the partition is mounted, but the disk system=
 can
> > only operate on it when unmounted, it could either a) unmount the=20
> > partition
> > or b) fail.
>=20
> Or c) block and request that the user either unmount the partition or
> cancel. Or d) block and warn the user that when they click "unmount", t=
he
> partition will be promptly unmounted, thus they should close anything f=
rom
> that partition that they currently have open (or risk losing data) or e=
lse
> click "cancel" to cancel the job queue.
>
> > The problem with a) is, that it's a bit beyond the control of
> > the user. If, as Axel says, unmounting would always work not heeding
> > pending vnodes, then the user might risk losing data, I suppose.
>=20
> I agree, that's a bit mean to pull the rug out from under the user like
> that. b) seems like a weak solution, too, though. c) and d) seem nicer =
to
> me. Is there any reason you can think of why either couldn't be made to=
=20
> work?

Why, yes. The job is executed in the kernel and while it would be no prob=
lem=20
to block it, I see some difficulties, how the user should be notified (an=
d=20
how to even get feedback from them). If we had the Interface Kit availabl=
e in=20
the kernel (not that I'm recommending that; surely not :-), we could simp=
ly=20
pop up an alert, but with the design as is, that can't be done without so=
me=20
additional userland service the kernel could use.

Mmh, we already discussed some time ago, how to move the (kernel)=20
notification message delivery to the registrar. The registrar would regis=
ter=20
via a to be defined interface with the kernel as an entity providing the=20
notification message delivery service. In the same manner some server/dae=
mon=20
(in doubt also the registrar) could register as kernel-user interaction=20
service. For simple multiple choice feedback requests (alerts) that shoul=
dn't=20
be that hard to do.

> > > What would we gain because of the latter?`
> >=20
> > Obviously that one can unmount a partition, while another app is prep=
aring
> > modifications for the same disk device (mind you, it doesn't even nee=
d to
> > be the same partition, nor does it play a role whether any changes ha=
ve
> > been made at all, yet).
> >=20
> > Just to throw another alternative onto the pitch: The Mount()/Unmount=
()
> > methods could have a boolean parameter indicating whether the operati=
on
> > shall be carried out immediately or being queued. Not sure, if that m=
akes
> > any sense in case of Mount(), though. Usually invoking the modifying
> > methods on a BPartition object indeed immediately changes the object.
> > That's a bit complicated for Mount(), since one can't get a valid dev=
_t
> > until the partition is really mounted.
> >=20
> > So, maybe only a `bool immediately =3D true' parameter for Unmount(),=
 while
> > Mount() would always work immediately and fail, if the partition was
> > modified?
>=20
> That sounds okay to me. So, mounting would fail if the partition in que=
stion
> is busy.

If you mean by `busy' that the partition will be affected by scheduled (o=
r=20
already executing) jobs (as I do), then it should definitely fail. But al=
so,=20
if the BPartition you're invoking Mount() on has been modified, even if t=
he=20
changes have not been committed yet. The reason is to avoid confusing=20
situations like that you invoke Uninitialize() on a partition (but not ye=
t=20
CommitModifications()) and the subsequent Mount() would succeed neverthel=
ess.=20
(Situation 2a BTW.)

Though, if invoked on another BPartition referring to the same physical=20
partition, the Mount() might succeed even if another user is preparing=20
modifications for the device/partition (situation 2b, and when considerin=
g=20
mount() as well, also 2c), depending on how we decide. If I understood yo=
u=20
correctly, you'd find it acceptable (reasonable? desirable?), if the Moun=
t()=20
would fail in that case (even if the modifications the other user is=20
preparing for the disk device wouldn't affect the partition in question?)=
.

> Immediate unmounting would fail is the partition is busy

Definitely.

>, but
> queued unmounting would be part of the job queue and thus succeed alway=
s.
> Correct?

If we also add a `force' parameter and `true' is supplied, then you are=20
correct. If `false' is supplied and there are open nodes when the attempt=
 to=20
unmount the partition is made, then the job (and subsequent jobs in the s=
ame=20
queue) would fail. If we add something like a kernel-user feedback featur=
e,=20
then we might have more options, e.g. dropping the `force' parameter and=20
rather ask the user whether to force the unmount, or keep it and ask the=20
user, if `false' was supplied...

CU, Ingo