Ok, thanks for the information on how to debug this. ;P Here's what's going
on:
Normally we get this when the USB cable is unplugged:
D/mountd ( 30): RequestMount /sdcard
D/mountd ( 30): mounting /dev/block/mmcblk0 at /sdcard
D/mountd ( 30): mount returned -1 errno: 22
D/mountd ( 30): mount failed, errno: 22
D/mountd ( 30): mounting /dev/block/mmcblk0p1 at /sdcard
D/mountd ( 30): mount returned 0 errno: 0
D/mountd ( 30): Write: media_mounted:/sdcard
If we remove have mmcblk0p2 mounted, we get only this:
D/mountd ( 30): RequestMount /sdcard
D/mountd ( 30): mounting /dev/block/mmcblk0 at /sdcard
D/mountd ( 30): mount returned -1 errno: 16
For those of us who don't have these error numbers memorized, which for the
sake of all that is right in the world I hope is all of us ;P:
#define EBUSY 16 /* Device or resource busy */
#define EINVAL 22 /* Invalid argument */
The code that is handling these error messages is here, in AutoMount.c:
255 if (result == 0) {
256 NotifyMediaState(mountPoint, MEDIA_MOUNTED, (flags &
MS_RDONLY) != 0);
257 } else if (errno == EBUSY) {
258 // ignore EBUSY, since it usually means the device is already
mounted
259 result = 0;
260 } else {
261 #if CREATE_MOUNT_POINTS
262 rmdir(mountPoint);
263 #endif
264 LOG_MOUNT("mount failed, errno: %d\n", errno);
265 }
Removing lines 257-259 does, in fact, fix the problem. When mmcblk0 is
specified instead of mmcblk0p1, this function needs to fail for it to bother
scanning partitions of the main device. Frankly, I disagree with mountd's
assumption that EBUSY there should mean "already mounted" (especially with
this counter example), and even if it were true I still believe it to be a
mistake: if I have mountd managing this mount, I would prefer it to either
know or not whether it is mounted and if I do so manually it should be an
error.
With this change I now get:
D/mountd ( 32): RequestMount /sdcard
D/mountd ( 32): mounting /dev/block/mmcblk0 at /sdcard
D/mountd ( 32): mount returned -1 errno: 16
D/mountd ( 32): mount failed, errno: 16
D/mountd ( 32): mounting /dev/block/mmcblk0p1 at /sdcard
D/mountd ( 32): mount returned 0 errno: 16
D/mountd ( 32): Write: media_mounted:/sdcard
Which seems perfectly reasonable to me and makes everything work correctly,
including the "someone formatted an SD card without a partition map" case
(which I didn't realize would ever come up: sorry about that).
I have submitted this as this new patch:
http://review.source.android.com/r/1964942af0f1
Sincerely,
Jay Freeman (saurik)
[EMAIL PROTECTED]
http://www.saurik.com/
--------------------------------------------------
From: "Mike Lockwood" <[EMAIL PROTECTED]>
Sent: Wednesday, November 19, 2008 3:18 PM
To: <[email protected]>
Subject: [android-porting] Re: Filesystems (yaffs2, jffs2 and nfs)
>
> Changing mountd.conf to mount mmcblk0p1 is a fine workaround for your
> problem, but won't work as a general solution. In particular, it will
> not work with SD cards that have a FAT file system starting at the
> first sector (with no partition map at all).
>
> I think the real problem is somewhere in mountd. Could you enable
> mountd logging by turning on ENABLE_LOG_MOUNT and ENABLE_LOG_SERVER in
> mountd.h and send me a logcat? Send me a dmesg too. Then I might be
> able to figure out a better solution.
>
> thanks,
> Mike
>
> On Wed, Nov 19, 2008 at 5:48 PM, Jay Freeman (saurik) <[EMAIL PROTECTED]>
> wrote:
>>
>> Ok, I've got it!!! I had to change "mmcblk0" to "mmcblk0p1" in
>> /etc/mountd.conf. This will probably fix Maxime's problem as well.
>>
>> I have uploaded this change to Gerrit at:
>> http://review.source.android.com/r/7507ee976e1c
>>
>> For the record, in case this clarifies things, here is complete order of
>> events I was experiencing before I made that change:
>>
>> 1) boot device
>> 2) notice that /sdcard mounted fine
>> 3) plug in USB cable
>> 4) select "mount" from USB notification
>> 5) notice that /sdcard correctly unmounted
>> 6) unplug USB cable
>> 7) /sdcard is immediately remounted
>> 8) repeat steps 3-7 a few times to verify sanity
>>
>> Ok, so far, so good. This is what I expect from an un-messed with device.
>>
>> 9) plug in USB cable
>> 10) mount /dev/block/mmcblk0p2 to /mnt (we now have:)
>> /dev/block/mmcblk0p1 /sdcard vfat rw,dirsync,... 0 0
>> /dev/block/mmcblk0p2 /mnt ext2 rw,errors=continue 0 0
>> 11) select "mount" from USB notification
>> 12) notice that /sdcard correctly unmounted
>> 13) unplug USB cable
>> 14) wait and wait and wait... no /sdcard
>>
>> This is not what I expected, and maid me frowny pants. :(
>>
>> 15) plug in USB cable (for adb shell)
>> 16) unmount /mnt
>> 17) unplug USB cable
>> 18) still no /sdcard
>>
>> It was this part I wasn't expecting even going into this e-mail, which
>> made
>> me think that maybe I should go seriously scan over the mountd
>> configuration
>> to make certain it wasn't broken (and it was). Yay!
>>
>> Sincerely,
>> Jay Freeman (saurik)
>> [EMAIL PROTECTED]
>> http://www.saurik.com/
>>
>> --------------------------------------------------
>> From: "Mike Lockwood" <[EMAIL PROTECTED]>
>> Sent: Tuesday, November 18, 2008 4:48 PM
>> To: <[email protected]>
>> Subject: [android-porting] Re: Filesystems (yaffs2, jffs2 and nfs)
>>
>>>
>>> If you boot from the SD card, do you have the files /dev/block/mmcblk0
>>> and /dev/block/mmcblk0p1? If those files are missing, then mountd
>>> will not attempt to mount the SD card.
>>>
>>> You might want to turn on:
>>>
>>> #define ENABLE_LOG_MOUNT
>>> #define ENABLE_LOG_SERVER
>>>
>>> in system/core/mountd/mountd.h to enable some extra logcat diagnostics
>>> in mountd so you can see what's going on.
>>>
>>> Mike
>>>
>>> On Tue, Nov 18, 2008 at 6:52 PM, Jay Freeman (saurik)
>>> <[EMAIL PROTECTED]>
>>> wrote:
>>>>
>>>> In my experience, using any part of the SD card makes /sdcard not work.
>>>> Example: if, after the system has already booted up and /sdcard is
>>>> mounted,
>>>> I mount a second partition off the SD card, everything is fine until I
>>>> next
>>>> need /sdcard to mount. Specifically, if I plug in the USB cable it
>>>> works,
>>>> if
>>>> I ask the G1 to mount over USB that even works (and /sdcard is
>>>> unmounted),
>>>> but when I unplug the USB cable nothing happens: I need to unmount my
>>>> second
>>>> partition to get Android to understand that the card isn't in use
>>>> anymore.
>>>> Maybe its doing something like checking the number of active usages of
>>>> the
>>>> base card rather than the one partition it wants or something (or maybe
>>>> its
>>>> something weird in mountd: I haven't even looked into how /sdcard works
>>>> yet). -J
>>>>
>>>> --------------------------------------------------
>>>> From: "Maxime Petazzoni" <[EMAIL PROTECTED]>
>>>> Sent: Tuesday, November 18, 2008 3:00 PM
>>>> To: "android-porting" <[email protected]>
>>>> Subject: [android-porting] Re: Filesystems (yaffs2, jffs2 and nfs)
>>>>
>>>>>
>>>>> I may have a similar problem here. I'm trying to run Android entirely
>>>>> off the SD card (actually, microSD, on the Zoom). I made three
>>>>> partitions :
>>>>>
>>>>> - /dev/mmcblk0p1, vfat, 1G, to be mounted as /sdcard for media data
>>>>> - /dev/mmcblk0p2, msdos, 10M, to host the uImage for U-Boot (i could
>>>>> have put it on the first partition, but here it's hidden from the
>>>>> user)
>>>>> - /dev/mmcblk0p3, ext3, 1.99G, to be mounted as the entire Android
>>>>> root filesystem
>>>>>
>>>>> Using the following bootargs : 'console=ttyS2,115200n8 ip=none rw
>>>>> rootwait root=/dev/mmcblk0p3 init=/init' and the following bootcmd :
>>>>> 'mmcinit;fatload mmc 0:2 0x81600000 uImage;bootm 0x81600000'. The
>>>>> system boots and runs fine, but there's nothing mounted in /sdcard.
>>>>>
>>>>> Did you ever got something similar ? How did you get the sdcard to be
>>>>> mounted by Android when not using NFS root ? When booting from NFS
>>>>> with the card already inserted, it works and /dev/block/mmcblk0p1 gets
>>>>> mounted as /sdcard.
>>>>>
>>>>> Thanks,
>>>>> - Maxime
>>>>>
>>>>> On Nov 11, 7:15 am, "Misael Lopez" <[EMAIL PROTECTED]> wrote:
>>>>>> > What I did for that is
>>>>>> > to split the sdcard into 2 partitions: fat for user data like
>>>>>> > music,
>>>>>> > videos, etc, and ext3 for the /data partition.
>>>>>>
>>>>>> Did you do something else apart from creating/formatting the
>>>>>> partitions? I tried the
>>>>>> same but Music application never accepted the card (even it the fat
>>>>>> partition is
>>>>>> mounted manually/automatically), it complained about SD card not
>>>>>> mounted.
>>>>>>
>>>>>> Misa
>>>>>>
>>>>>> 2008/11/11 Sean McNeil <[EMAIL PROTECTED]>:
>>>>>>
>>>>>>
>>>>>>
>>>>>> > mvniekerk wrote:
>>>>>> >> Well, I can help you with this much - jffs2 + Android = No Go. It
>>>>>> >> will
>>>>>>
>>>>>> > Not true. Android runs perfectly on the Openmoko Freerunner using
>>>>>> > JFFS2
>>>>>> > for root and system. You need to qualify your statement as the only
>>>>>> > real
>>>>>> > partition that needs mmap is the /data partition. What I did for
>>>>>> > that
>>>>>> > is
>>>>>> > to split the sdcard into 2 partitions: fat for user data like
>>>>>> > music,
>>>>>> > videos, etc, and ext3 for the /data partition.
>>>>>>
>>>>>> >> run a few apps until the actual zygote stuff needs to run. mmap is
>>>>>> >> the
>>>>>> >> thing that will screw you over - you only get mmap with read only
>>>>>> >> jffs2.
>>>>>> >> yaffs2 + NOR = No Go. It will fall over and flop.
>>>>>> >> UBIFS + NOR + Android = Works well actually. Got it running on our
>>>>>> >> iMX31 board with NOR. I'll post some instructions to get UBIFS
>>>>>> >> working
>>>>>> >> if you need it. UBIFS = JFFS3. It has compression and a lot of
>>>>>> >> other
>>>>>> >> cool stuff. It also scales well.
>>>>>>
>>>>>> >> On Nov 10, 4:10 pm, Markus <[EMAIL PROTECTED]> wrote:
>>>>>>
>>>>>> >>> Hi,
>>>>>>
>>>>>> >>> yes, we might change to a different file system, but actually,
>>>>>> >>> Android
>>>>>> >>> uses yaffs2 as main file system or at least it seems like this if
>>>>>> >>> you
>>>>>> >>> hack into its configuration files. To be honest, we do not know,
>>>>>> >>> if
>>>>>> >>> this problem is caused by the file system or something else as we
>>>>>> >>> are
>>>>>> >>> able to do file operations in /data/app during the booting
>>>>>> >>> process.
>>>>>> >>> The kernel panic occurs after Android finished the booting
>>>>>> >>> process.
>>>>>> >>> So
>>>>>> >>> our guess is that Android starts something, that watches the file
>>>>>> >>> system (especially /data/app) and that this service is causing
>>>>>> >>> our
>>>>>> >>> problem. Unfortunately, we could not yet locate, which tool is
>>>>>> >>> responsible... any guess, what is started in the end of the
>>>>>> >>> booting
>>>>>> >>> process, that might cause our problem?
>>>>>>
>>>>>> >>> Below, a log of the kernel panic.
>>>>>>
>>>>>> >>> Bye
>>>>>> >>> Markus
>>>>>>
>>>>>> >>> busybox cp ApiDemos.apk test
>>>>>> >>> Unable to handle kernel paging request at virtual address
>>>>>> >>> 00100104
>>>>>> >>> pgd = c70a4000
>>>>>> >>> [00100104] *pgd=870a2031, *pte=857180dd, *ppte=8571880e
>>>>>> >>> Internal error: Oops: 81f [#1] PREEMPT
>>>>>> >>> Modules linked in:
>>>>>> >>> CPU: 0 Not tainted (2.6.24-140-g68eb4b4 #77)
>>>>>> >>> PC is at android_unlock_suspend+0x60/0x170
>>>>>> >>> LR is at android_unlock_suspend+0x34/0x170
>>>>>> >>> pc : [<c01ff8b4>] lr : [<c01ff888>] psr: 60000193
>>>>>> >>> sp : c711bea8 ip : c039bac4 fp : c711bee4
>>>>>> >>> r10: c711a000 r9 : 000001e0 r8 : 60000113
>>>>>> >>> r7 : c7de20a0 r6 : c039babc r5 : c039babc r4 : c7de20e0
>>>>>> >>> r3 : c7c35da8 r2 : 00100100 r1 : 00200200 r0 : c7de20e0
>>>>>> >>> Flags: nZCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
>>>>>> >>> Control: 00e5387f Table: 870a4000 DAC: 00000015
>>>>>> >>> Process FileObserver (pid: 1675, stack limit = 0xc711a260)
>>>>>> >>> Stack: (0xc711bea8 to 0xc711c000)
>>>>>> >>> bea0: c710401c c7cfac40 c711bed4 c711bec0 c00603cc
>>>>>> >>> c006035c
>>>>>> >>> bec0: c73dc3c0 00000000 c73dc3d0 c7de20a0 c73dc3c0 c711a000
>>>>>> >>> c711befc
>>>>>> >>> c711bee8
>>>>>> >>> bee0: c00c4f90 c01ff860 c73dc3c0 46a2cba4 c711bf4c c711bf00
>>>>>> >>> c00c57d0
>>>>>> >>> c00c4f30
>>>>>> >>> bf00: c003f92c 46a2cb84 c7cfac70 00000000 c7cfac40 c005b298
>>>>>> >>> c711bf18
>>>>>> >>> c711bf18
>>>>>> >>> bf20: c02bfa58 c7043ea0 46a2cb84 c711bf78 00000200 c0025004
>>>>>> >>> c711a000
>>>>>> >>> 41046fc0
>>>>>> >>> bf40: c711bf74 c711bf50 c00961a4 c00c5634 c711bf74 c711bf60
>>>>>> >>> c7043ea0
>>>>>> >>> fffffff7
>>>>>> >>> bf60: 00000000 00000000 c711bfa4 c711bf78 c00965ec c00960fc
>>>>>> >>> 00000000
>>>>>> >>> 00000000
>>>>>> >>> bf80: 001ce0b0 00000001 00000f4c ad352cd8 001cf5b8 00000003
>>>>>> >>> 00000000
>>>>>> >>> c711bfa8
>>>>>> >>> bfa0: c0024e80 c00965b4 00000f4c ad352cd8 0000001e 46a2cb84
>>>>>> >>> 00000200
>>>>>> >>> fd1fafed
>>>>>> >>> bfc0: 00000f4c ad352cd8 001cf5b8 00000003 46a2cda0 41046fd4
>>>>>> >>> 41046fc0
>>>>>> >>> 00000001
>>>>>> >>> bfe0: ad353458 46a2cb48 ad3414c9 afe0b50c 00000010 0000001e
>>>>>> >>> 00ff00ff
>>>>>> >>> 00ff00ff
>>>>>> >>> Backtrace:
>>>>>> >>> [<c01ff854>] (android_unlock_suspend+0x0/0x170) from [<c00c4f90>]
>>>>>> >>> (remove_kevent+0x6c/0x94)
>>>>>> >>> [<c00c4f24>] (remove_kevent+0x0/0x94) from [<c00c57d0>]
>>>>>> >>> (inotify_read
>>>>>> >>> +0x1a8/0x1e4)
>>>>>> >>> r4:46a2cba4
>>>>>> >>> [<c00c5628>] (inotify_read+0x0/0x1e4) from [<c00961a4>] (vfs_read
>>>>>> >>> +0xb4/0x144)
>>>>>> >>> [<c00960f0>] (vfs_read+0x0/0x144) from [<c00965ec>] (sys_read
>>>>>> >>> +0x44/0x70)
>>>>>> >>> r7:00000000 r6:00000000 r5:fffffff7 r4:c7043ea0
>>>>>> >>> [<c00965a8>] (sys_read+0x0/0x70) from [<c0024e80>]
>>>>>> >>> (ret_fast_syscall
>>>>>> >>> +0x0/0x2c)
>>>>>> >>> r7:00000003 r6:001cf5b8 r5:ad352cd8 r4:00000f4c
>>>>>> >>> Code: e5965000 e5812000 e5843000 e59c3000 (e5821004)
>>>>>> >>> Kernel panic - not syncing: Fatal exception
>>>>>>
>>>>>> >>> On 9 Nov., 10:16, mvniekerk <[EMAIL PROTECTED]> wrote:
>>>>>>
>>>>>> >>>> Your answer lies in UBIFS. There is a port for kernel 2.6.24 up
>>>>>> >>>> to
>>>>>> >>>> 2.6.27. UBIFS is JFFS3 if you like - and it does support mmap.
>>>>>> >>>> If
>>>>>> >>>> your
>>>>>> >>>> flash chip is of the NOR-type then YAFFS2 will not work - that
>>>>>> >>>> is
>>>>>> >>>> what
>>>>>> >>>> makes UBIFS so sweet!
>>>>>> >>>> To set up a UBI volume for UBIFS is bit of a schlep, but once
>>>>>> >>>> done
>>>>>> >>>> it
>>>>>> >>>> is a cool piece of equipment.
>>>>>>
>>>>>> >>>> On Nov 6, 11:39 pm, Markus <[EMAIL PROTECTED]> wrote:
>>>>>>
>>>>>> >>>>> Hi,
>>>>>>
>>>>>> >>>>> it is the init process, that cannot start. The kernel is always
>>>>>> >>>>> booting fine and only the Android init process is not able to
>>>>>> >>>>> do
>>>>>> >>>>> its
>>>>>> >>>>> job. For yaffs2, the booting process stops like
>>>>>> >>>>> inhttp://groups.google.com/group/android-porting/browse_thread/thread/d...
>>>>>> >>>>> - I'm sorry, that I can't post my own message at the moment,
>>>>>> >>>>> but
>>>>>> >>>>> I
>>>>>> >>>>> do
>>>>>> >>>>> not have access to the hardware right now to flash
>>>>>> >>>>> everything...
>>>>>>
>>>>>> >>>>> Like in the link above, we get the same problem about the magic
>>>>>> >>>>> number, while Android tries to load the core.jar file. After 4
>>>>>> >>>>> tries,
>>>>>> >>>>> Android resigns and reboots.
>>>>>>
>>>>>> >>>>> bye
>>>>>> >>>>> Markus
>>>>>>
>>>>>> >>>>> On 6 Nov., 17:22, "Gergely Kis" <[EMAIL PROTECTED]> wrote:
>>>>>>
>>>>>> >>>>>> Hi,
>>>>>>
>>>>>> >>>>>> Could you give more information regarding "Android was not
>>>>>> >>>>>> able
>>>>>> >>>>>> to
>>>>>> >>>>>> boot onyaffs2". What were the actual error messages? Did the
>>>>>> >>>>>> kernel
>>>>>> >>>>>> hang, or the init process?
>>>>>>
>>>>>> >>>>>> Best Regards,
>>>>>> >>>>>> Gergely
>>>>>>
>>>>>> >>>>>> On Thu, Nov 6, 2008 at 4:18 PM, Markus <[EMAIL PROTECTED]> wrote:
>>>>>>
>>>>>> >>>>>>> Hi,
>>>>>>
>>>>>> >>>>>>> as I wrote in Android Internals, we ported Android to an
>>>>>> >>>>>>> i.MX31.
>>>>>> >>>>>>> Unfortunately, we have some issues with the file system.
>>>>>> >>>>>>> If I use NFS as file system with a modified init.rc config,
>>>>>> >>>>>>> everything
>>>>>> >>>>>>> seems to work well, but this is no option for us as permanent
>>>>>> >>>>>>> file
>>>>>> >>>>>>> system, so we decided to useyaffs2as file system. As this did
>>>>>> >>>>>>> not
>>>>>> >>>>>>> work (Android was not able to boot), we changed to jffs2.
>>>>>> >>>>>>> jffs2
>>>>>> >>>>>>> boots
>>>>>> >>>>>>> fine as long as we use a read-only file system. After
>>>>>> >>>>>>> booting,
>>>>>> >>>>>>> we
>>>>>> >>>>>>> can
>>>>>> >>>>>>> start many applications, but it seems that those requiring
>>>>>> >>>>>>> file
>>>>>> >>>>>>> write
>>>>>> >>>>>>> operations fail to start, e.g. the webbrowser. If we change
>>>>>> >>>>>>> init.rc
>>>>>> >>>>>>> config to give file-write permissions, Android is not able to
>>>>>> >>>>>>> boot
>>>>>> >>>>>>> anymore.
>>>>>>
>>>>>> >>>>>>> So we have decided to use a mixture ofyaffs2and jffs2, after
>>>>>> >>>>>>> we
>>>>>> >>>>>>> saw
>>>>>> >>>>>>> this idea at the armv4 port. The basic idea is, that all mmap
>>>>>> >>>>>>> operations are done onyaffs2, as jffs2 does not support them.
>>>>>> >>>>>>> At
>>>>>> >>>>>>> the
>>>>>> >>>>>>> moment, we split the file system to two parts: /data is
>>>>>> >>>>>>> located
>>>>>> >>>>>>> on our
>>>>>> >>>>>>> yaffs2partition, everything else on our jffs2 partition. The
>>>>>> >>>>>>> system
>>>>>> >>>>>>> boots fine and we can run every application. But now, it is
>>>>>> >>>>>>> getting
>>>>>> >>>>>>> confusing: As soon as Android has finished booting, it is
>>>>>> >>>>>>> impossible
>>>>>> >>>>>>> to write/delete files in /data/app - if we do, we get a
>>>>>> >>>>>>> kernel
>>>>>> >>>>>>> panic,
>>>>>> >>>>>>> which reports FileObserver to fail. This does not happen, if
>>>>>> >>>>>>> we
>>>>>> >>>>>>> do
>>>>>> >>>>>>> file accesses before Android has finished its booting
>>>>>> >>>>>>> process.
>>>>>>
>>>>>> >>>>>>> Remembering that we had some cases, in which it was necessary
>>>>>> >>>>>>> to
>>>>>> >>>>>>> start
>>>>>> >>>>>>> the system with strace running in the background (and
>>>>>> >>>>>>> discarding
>>>>>> >>>>>>> the
>>>>>> >>>>>>> log), I booted theyaffs2/jffs2 system with strace in the
>>>>>> >>>>>>> background.
>>>>>> >>>>>>> Now, I am able to access files in /data/app, I just get
>>>>>> >>>>>>> "syscall:
>>>>>> >>>>>>> unknown syscall trap 0xe1a00000" reported to my debug
>>>>>> >>>>>>> console.
>>>>>> >>>>>>> In
>>>>>> >>>>>>> this
>>>>>> >>>>>>> mode, it is also possible to run applications directly from
>>>>>> >>>>>>> Eclipse on
>>>>>> >>>>>>> the target device.
>>>>>>
>>>>>> >>>>>>> So can anybody tell me what is going wrong, if I use
>>>>>> >>>>>>> ayaffs2only
>>>>>> >>>>>>> file system? And why does strace heal those problems with
>>>>>> >>>>>>> ayaffs2/
>>>>>> >>>>>>> jffs2 system? It just makes the system slower...
>>>>>>
>>>>>> >>>>>>> bye
>>>>>> >>>>>>> Markus
>>>>> >
>>>>>
>>>>
>>>> >
>>>>
>>>
>>>
>>>
>>> --
>>> Mike Lockwood
>>> Google android team
>>>
>>> >
>>>
>>
>> >
>>
>
>
>
> --
> Mike Lockwood
> Google android team
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
unsubscribe: [EMAIL PROTECTED]
website: http://groups.google.com/group/android-porting
-~----------~----~----~----~------~----~------~--~---