Re: To Unmount Or Not To Unmount

Ingo Weinhold <bonefish-CFLBMwTPW48UNGrzBIF7/[email protected]> Tue, 23 Sep 2003 23:09:44 +0200
Newsgroups gmane.os.openbeos.storage
Message-ID <[email protected]>
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, even
> > > 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 calls,
> > 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 VFS
> is all about, right?

I should clarify the situations that can occur:

1) Partition is busy: There are scheduled or already executing jobs, that=
=20
affect the partition. Jobs are scheduled, when=20
BDiskDevice::CommitModifications() is invoked.

2) A user has invoked BDiskDevice::PrepareModifications() (started a=20
transaction, to use that term) but not yet called=20
BDiskDevice::{Cancel,Commit}Modifications() (rolled back respectively=20
committed the transaction).
a) Mount()/Unmount() is invoked on a BPartition object belonging to the=20
very same BDiskDevice object.
b) Mount()/Unmount() is invoked on a BPartition object belonging to anoth=
er=20
user (but of course referring to the same partition).
c) mount()/unmount() is invoked for the partition.

There's no further distinction of cases for 1), because in any case, the=20
same must happen: mount(), unmount(), Mount(), Unmount() must fail, for=20
otherwise we'd risk, that something bad will happen, if the mount state=20
changes behind the back of a job that operates on that partition.

What shall happen in the case 2)a)-c) was subject of my mail. :-)

> > (correct? I've forgotten how fine the locking granularity is when you
> > prep modifications, but I think it's by device isn't it?).

Yep it is.

> > Furthermore,=20
> > once Commit() has been called, aren't the partitions of interest lock=
ed=20
> > until all the jobs that affect them are completed?

Not locked, but marked busy. That is you can still read/write lock them (=
in=20
the kernel), but certain operations on it shall fail, namely preparing ne=
w=20
modifications for them (more precisely: PrepareModifications() will work=20
fine, but any operation that would affect a busy partition will fail), an=
d=20
mounting/unmounting.

> > This seems like an=20
> > (almost :-) reasonable restriction to me: once you start planning a s=
et=20
> > of jobs that involve a partition, you can't mount/unmount it until yo=
u=20
> > cancel or no more=20
> > jobs remain that affect that partition.

Please don't mix that up. Until you commit the changes you're in the=20
situation 2) (and there aren't any jobs yet), that is, in principle,=20
there'd be no problem with mounting/unmounting immediately. At least from=
=20
the DDM point of view.

> > 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, perhaps
> > 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 drive
> 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 :-)

Well, as far as the jobs go, there are no choices. As soon as they are=20
created, the partitions that are going to be affected are marked busy and=
=20
mounting/unmounting and modification requests must fail.
That point is, that the jobs are only created when the modifications are=20
committed. Until then, we are free to mount/unmount would-be affected=20
partitions.

[...]
> > > 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 committed,
> > > 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 can
> > > 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 least,
> > 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 for
> > it.
>=20
> Is it really hybrid? It sounds like Mount()/Unmount() would just call
> PrepareModifications() if needed themselves.

I didn't think of that. That would also be where the synchronous=20
CommitModifications() mode would come handy... in case anyone still=20
remembers the discussion about that. ;-)

The drawback of that approach -- if one considers it one -- is that one=20
cannot mount/unmount a partition when another app is preparing=20
modifications for the same disk device.

> Which would kinda be the
> job of mount()/unmount().

Here you lost me.

> But I think it's often (for the user) more appropriate to fail the
> mounting process in that moment (as Tyler suggested, methinks).

OK. I imagine an error message like `An error occured: General OS error.'=
=20
Alright, just kidding... ;-)

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

What I was thinking of, was, that when a job gets executed, it would itse=
lf=20
first invoke the respective Validate*() hooks of the disk system again an=
d=20
learn, if the disk system needs a currently mounted partition unmounted, =
or=20
if something's fishy and it should rather fail on the spot.

So, if it realizes that the partition is mounted, but the disk system can=
=20
only operate on it when unmounted, it could either a) unmount the partiti=
on=20
or b) fail. The problem with a) is, that it's a bit beyond the control of=
=20
the user. If, as Axel says, unmounting would always work not heeding=20
pending vnodes, then the user might risk losing data, I suppose.

> > Of course, if the user if playing
> > MP3s or
> > whatever off the partition at the time, we'd need a way to notify the
> > 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 file
> anyway...

Cool feature. :-)
It must be used with care, I believe, for one gambles with the user's dat=
a.

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

I don't really like having different semantics for Mount() and Unmount().=
=20
Either both should have the hybrid semantics or neither one should.

> What would we gain because of the latter?`

Obviously that one can unmount a partition, while another app is preparin=
g=20
modifications for the same disk device (mind you, it doesn't even need to=
=20
be the same partition, nor does it play a role whether any changes have=20
been made at all, yet).

Just to throw another alternative onto the pitch: The Mount()/Unmount()=20
methods could have a boolean parameter indicating whether the operation=20
shall be carried out immediately or being queued. Not sure, if that makes=
=20
any sense in case of Mount(), though. Usually invoking the modifying=20
methods on a BPartition object indeed immediately changes the object.=20
That's a bit complicated for Mount(), since one can't get a valid dev_t=20
until the partition is really mounted.

So, maybe only a `bool immediately =3D true' parameter for Unmount(), whi=
le=20
Mount() would always work immediately and fail, if the partition was=20
modified?

CU, Ingo