Re: To Unmount Or Not To Unmount

Tyler Dauwalder <tyler-cyCl/[email protected]> Thu, 25 Sep 2003 23:26:47 -0700
Newsgroups gmane.os.openbeos.storage
Message-ID <20030925232647.351.40@heroin_bob.attbi.com>
On 2003-09-23 at 14:09:44 [-0700], Ingo Weinhold wrote:
>=20
> On 2003-09-23 at 20:38:24 [+0200], Axel D=F6rfler wrote:
> > Tyler Dauwalder <tyler-cyCl/[email protected]> wrote:
> > > On 2003-09-22 at 13:24:33 [-0700], Ingo Weinhold wrote:
> > > > In favor of unmounting on commit speaks, that the behavior would =
be
> > > > consistent with the other modifying methods. On the other hand,
> > > > mounting/unmounting can be done by a third party at any time, eve=
n
> > > > if one
> > > > is preparing modifications at that time.
> > > I thought we were going to serialize all mounting and unmounting
> > > through
> > > the ddm. Thus, the system unmount() call ought to work via ddm call=
s,
> > > which
> > > means (assuming we use "on commit" semantics) that unmount() will
> > > simply
> > > fail if someone is preparing modifications on a given partition's
> > > device
> >=20
> > That's what I thought, too... that's what the integration with the VF=
S
> > 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, th=
at
> 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 the
> very same BDiskDevice object.
> b) Mount()/Unmount() is invoked on a BPartition object belonging to ano=
ther
> 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, th=
e
> same must happen: mount(), unmount(), Mount(), Unmount() must fail, for
> otherwise we'd risk, that something bad will happen, if the mount state
> 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. :-)

I really did understand that, even if it perhaps didn't seem like it. :-)=
=20
When you said, "On the other hand, mounting/unmounting can be done by a=20
third party at any time, even if one is preparing modifications at that=20
time", it just sounded as though you were implying a call to mount() or=20
unmount() could go and do things behind the back of the ddm. That being=20
said, having the cases enumerated is useful. :-)

> > > Furthermore,
> > > once Commit() has been called, aren't the partitions of interest lo=
cked
> > > until all the jobs that affect them are completed?
>=20
> Not locked, but marked busy. That is you can still read/write lock them=
 (in
> the kernel), but certain operations on it shall fail, namely preparing =
new
> modifications for them (more precisely: PrepareModifications() will wor=
k
> fine, but any operation that would affect a busy partition will fail), =
and
> mounting/unmounting.

Okay.

> > > This seems like an
> > > (almost :-) reasonable restriction to me: once you start planning a=
 set
> > > of jobs that involve a partition, you can't mount/unmount it until =
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 fr=
om
> the DDM point of view.

No, I wasn't mixed up (at least, I don't think I was :-). I was saying it=
=20
would seem reasonable to me to disallow mounting and unmounting anything =
on=20
a device from the time PrepareModifications() was called on a device unti=
l=20
no shadow partitions were left for it, and then disallow mounting and=20
unmounting any busy partitions as long as they were still marked busy, ju=
st=20
as is implied by the suggestion below that Mount() and Unmount() call=20
PrepareModifications() on their own as needed.

> > > 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, perhap=
s
> > > 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, b=
ut
> > > 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 driv=
e
> > status; I could imagine that their operation is different when the di=
sk
> > 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 are
> created, the partitions that are going to be affected are marked busy a=
nd
> mounting/unmounting and modification requests must fail.
> That point is, that the jobs are only created when the modifications ar=
e
> committed. Until then, we are free to mount/unmount would-be affected
> partitions.

I think his point was that, for example, whoever is responsible for resiz=
ing=20
the bfs partition is likely going to want to know whether the partition i=
s=20
mounted or not, assuming resizing while mounted is supported.

> [...]
> > > > So, perhaps a hybrid approach is the best solution: When one has
> > > > already
> > > > called PrepareModifications() on the device, the Mount() and
> > > > Unmount()
> > > > invocations will take effect after the modifications are committe=
d,
> > > > otherwise the mounting/unmounting is done immediately.
> > > >
> > > > Mmh, maybe that's confusing? It would make the mount/unmount
> > > > handling in
> > > > the disk device manager a bit more complicated, but as far as I c=
an
> > > > judge
> > > > it at the moment, it should be feasible.
> > > I don't like the hybrid in general. I think I would rather see
> > > Mount() and
> > > Unmount() follow the rules like everybody else. For Mount() at leas=
t,
> > > I
> > > don't see any gain in making it work in two different ways. For
> > > Unmount(),
> > > though, perhaps the hybrid approach would be worth the effort, just
> > > to
> > > allow a partition to be unmounted even if jobs are being prepared f=
or
> > > it.
> >=20
> > Is it really hybrid? It sounds like Mount()/Unmount() would just call
> > PrepareModifications() if needed themselves.
>=20
> I didn't think of that. That would also be where the synchronous
> CommitModifications() mode would come handy... in case anyone still
> remembers the discussion about that. ;-)

I'd forgotten, but I remember now. :-)

> The drawback of that approach -- if one considers it one -- is that one
> cannot mount/unmount a partition when another app is preparing
> modifications for the same disk device.
>=20
> > > > 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 Resize(=
)
> > > > would
> > > > automagically do the unmounting (or at least mark the partition t=
o
> > > > 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 it=
self
> first invoke the respective Validate*() hooks of the disk system again =
and
> learn, if the disk system needs a currently mounted partition unmounted=
, 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 c=
an
> only operate on it when unmounted, it could either a) unmount the parti=
tion
> or b) fail.=20

Or c) block and request that the user either unmount the partition or=20
cancel. Or d) block and warn the user that when they click "unmount", the=
=20
partition will be promptly unmounted, thus they should close anything fro=
m=20
that partition that they currently have open (or risk losing data) or els=
e=20
click "cancel" to cancel the job queue.=20

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

I agree, that's a bit mean to pull the rug out from under the user like=20
that. b) seems like a weak solution, too, though. c) and d) seem nicer to=
=20
me. Is there any reason you can think of why either couldn't be made to w=
ork?

> > > Of course, if the user if playing
> > > MP3s or
> > > whatever off the partition at the time, we'd need a way to notify t=
he
> > > user
> > > to stop using the partition so it may be unmounted for processing.
> >=20
> > That won't be necessary - the VFS will be able to unmount partitions =
at
> > any time; open descriptors won't prevent that any longer, they will
> > just be invalidated - and since that's the only connection to the fil=
e
> > anyway...
>=20
> Cool feature. :-)
> It must be used with care, I believe, for one gambles with the user's d=
ata.

Yeah, it does seem a bit sketchy.

> > > So, to sum up, I think I would prefer to use "on commit" semantics
> > > and try
> > > and get the rest of the system to work reasonably and logically
> > > within the
> > > normal DiskDevice job framework, with perhaps the exception of
> > > allowing
> > > hybrid semantics with Unmount() to allow unmounting while jobs are
> > > being
> > > prepped. What do you think?
>=20
> I don't really like having different semantics for Mount() and Unmount(=
).
> Either both should have the hybrid semantics or neither one should.

Fine.

> > What would we gain because of the latter?`
>=20
> Obviously that one can unmount a partition, while another app is prepar=
ing
> modifications for the same disk device (mind you, it doesn't even need =
to
> be the same partition, nor does it play a role whether any changes have
> 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 operation
> shall be carried out immediately or being queued. Not sure, if that mak=
es
> 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(), w=
hile
> Mount() would always work immediately and fail, if the partition was
> modified?

That sounds okay to me. So, mounting would fail if the partition in quest=
ion=20
is busy. Immediate unmounting would fail is the partition is busy, but=20
queued unmounting would be part of the job queue and thus succeed always.=
=20
Correct?

-Tyler