aboutsummaryrefslogtreecommitdiff
path: root/block
AgeCommit message (Collapse)Author
2012-07-17vvfat: Do not clobber the user's geometryMarkus Armbruster
vvfat creates a virtual VFAT filesystem with a certain logical geometry that depends on its options. It sets the "geometry hint" to this geometry. It is the only block driver to do this. The geometry hint is about about *physical* geometry, and used only by certain hard disk device models. vvfat's hint is normally invisible for device models, because bdrv_open() puts a raw format on top of vvfat's fat protocol. That raw format is where drive_init() puts the user's geometry (if any), and where the device model gets it from. Nobody complained, because the default physical geometry is the same as vvfat's logical geometry: opts LCHS def. PCHS 1024,16,63 same :32: 1024,16,63 same :16: 1024,16,63 same :12: 64,16,63 same Except when you specify :floppy: opts LCHS def. PCHS :floppy: 80, 2,36 5,16,63 :32:floppy: 80, 2,36 5,16,63 :16:floppy: 80, 2,36 5,16,63 :12:floppy: 80, 2,18 2,16,63 Silly thing to do for use with a hard disk. However, the "raw" format can be suppressed by adding an redundant-looking "format=vvfat" to "file=fat:FOO". Then, vvfat's hint clobbers the user's geometry, i.e. -drive options cyls, heads, secs get silently ignored. Don't do that. No change without format=vvfat. With it, the user's hard disk geometry (-drive options cyls, heads, secs) is now obeyed, and the default hard disk geometry with :floppy: now matches the one without format=vvfat. Signed-off-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-17vvfat: Fix partition tableMarkus Armbruster
Unless parameter ":floppy:" is given, vvfat creates a virtual image with DOS MBR defining a single partition which holds the FAT file system. The size of the virtual image depends on the width of the FAT: 32 MiB (CHS 64, 16, 63) for 12 bit FAT, 504 MiB (CHS 1024, 16, 63) for 16 and 32 bit FAT, leaving (64*16-1)*63 = 64449 and (1024*16-1)*64 = 1032129 sectors for the partition. However, it screws up the end of the partition in the MBR: FAT width param. start CHS end CHS start LBA size :32: 0,1,1 1023,14,63 63 1032065 :16: 0,1,1 1023,14,55 63 1032057 :12: 0,1,1 63,14,55 63 64377 The actual FAT file system nevertheless assumes the partition has 1032129 or 64449 sectors. Oops. Signed-off-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-17sheepdog: do not blindly memset all read buffersChristoph Hellwig
Only buffers that map to unallocated blocks need to be zeroed. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-17sheepdog: always use coroutine-based network functionsMORITA Kazutaka
This reduces some code duplication. Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09Merge remote-tracking branch 'mjt/mjt-iov2' into stagingAnthony Liguori
* mjt/mjt-iov2: rewrite iov_send_recv() and move it to iov.c cleanup qemu_co_sendv(), qemu_co_recvv() and friends export iov_send_recv() and use it in iov_send() and iov_recv() rename qemu_sendv to iov_send, change proto and move declarations to iov.h change qemu_iovec_to_buf() to match other to,from_buf functions consolidate qemu_iovec_copy() and qemu_iovec_concat() and make them consistent allow qemu_iovec_from_buffer() to specify offset from which to start copying consolidate qemu_iovec_memset{,_skip}() into single function and use existing iov_memset() rewrite iov_* functions change iov_* function prototypes to be more appropriate virtio-serial-bus: use correct lengths in control_out() message Conflicts: tests/Makefile Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2012-07-09Merge remote-tracking branch 'kwolf/for-anthony' into stagingAnthony Liguori
* kwolf/for-anthony: (24 commits) block: Factor bdrv_read_unthrottled() out of guess_disk_lchs() qtest: Tidy up temporary files properly fdc: Drop broken code for user-defined floppy geometry fdc_test: introduce test_sense_interrupt fdc_test: update media_change test fdc: fix interrupt handling fdc: rewrite seek and DSKCHG bit handling block: introduce bdrv_swap, implement bdrv_append on top of it block: copy over job and dirty bitmap fields in bdrv_append raw: hook into blkdebug blkdebug: optionally tie errors to a specific sector blkdebug: store list of active rules blkdebug: pass getlength to underlying file blkdebug: tiny cleanup blkdebug: remove sync i/o events sheepdog: traverse pending_list from the first for each time sheepdog: split outstanding list into inflight and pending sheepdog: make sure we don't free aiocb before sending all requests sheepdog: use coroutine based socket functions in coroutine context sheepdog: restart I/O when socket becomes ready in do_co_req() ...
2012-07-09raw: hook into blkdebugPaolo Bonzini
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09blkdebug: optionally tie errors to a specific sectorPaolo Bonzini
This makes blkdebug scripts more powerful, and independent of the exact sequence of operations performed by streaming. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09blkdebug: store list of active rulesPaolo Bonzini
This prepares for the next patch, where some active rules may actually not trigger depending on input to readv/writev. Store the active rules in a SIMPLEQ (so that it can be emptied easily with QSIMPLEQ_INIT), and fetch the errno/once/immediately arguments from there. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09blkdebug: pass getlength to underlying filePaolo Bonzini
This is required when using blkdebug with raw format. Unlike qcow2/QED, raw asks blkdebug for the length of the file, it doesn't get it from a header. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09blkdebug: tiny cleanupPaolo Bonzini
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09blkdebug: remove sync i/o eventsPaolo Bonzini
These are unused, except (by mistake more or less) in QED. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09sheepdog: traverse pending_list from the first for each timeMORITA Kazutaka
The pending list can be modified in other coroutine context sd_co_rw_vector, so we need to traverse the list from the first again after we send the pending request. Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09sheepdog: split outstanding list into inflight and pendingMORITA Kazutaka
outstanding_list_head is used for both pending and inflight requests. This patch splits it and improves readability. Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09sheepdog: make sure we don't free aiocb before sending all requestsMORITA Kazutaka
This patch increments the pending counter before sending requests, and make sures that aiocb is not freed while sending them. Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09sheepdog: use coroutine based socket functions in coroutine contextMORITA Kazutaka
This removes blocking network I/Os in coroutine context. Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09sheepdog: restart I/O when socket becomes ready in do_co_req()MORITA Kazutaka
Currently, no one reenters the yielded coroutine. This fixes it. Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09sheepdog: fix dprintf format stringsMORITA Kazutaka
This fixes warnings about dprintf format in debug mode. Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09qcow2: preserve free_byte_offset when qcow2_alloc_bytes() failsStefan Hajnoczi
When qcow2_alloc_clusters() error handling code was introduced in commit 5d757b563d59142ca81e1073a8e8396750a0ad1a, the value of free_byte_offset was clobbered in the error case. This patch keeps free_byte_offset at 0 so we will try to allocate clusters again next time this function is called. Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-09qcow2: fix #ifdef'd qcow2_check_refcounts() callersStefan Hajnoczi
The DEBUG_ALLOC qcow2.h macro enables additional consistency checks throughout the code. This makes it easier to spot corruptions that are introduced during development. Since consistency check is an expensive operation the DEBUG_ALLOC macro is used to compile checks out in normal builds and qcow2_check_refcounts() calls missed the addition of a new function argument. Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-07-02ISCSI: force use of sg for SMC and SSC devicesRonnie Sahlberg
If the device we open is a SMC or SSC device, then force the use of sg. We dont have any medium changer or tape emulation so only passthrough via real sg or scsi-generic via iscsi would work anyway. Forcing sg also makes qemu skip trying to read from the device to guess the image format by reading from the device (find_image_format()). SMC devices do not implement READ6/10/12/16 so it is not possible to read from them (SSC have different CDBs). With this patch I can successfully manage a SMC device wiht iscsi in passthrough mode. Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com> [Added TYPE_TAPE handling - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-07-02ISCSI: Add SCSI passthrough via scsi-generic to libiscsiRonnie Sahlberg
Update iscsi to allow passthrough of SG_IO scsi commands when the iscsi device is forced to be scsi-generic. Implement both bdrv_ioctl() and bdrv_aio_ioctl() in the iscsi backend, emulate the SG_IO ioctl and pass the SCSI commands across to the iscsi target. This allows end-to-end passthrough of SCSI all the way from the guest, to qemu, via scsi-generic, then libiscsi all the way to the iscsi target. To activate this you need to specify that the iscsi lun should be treated as a scsi-generic device. Example: -device lsi -device scsi-generic,drive=MyISCSI \ -drive file=iscsi://10.1.1.125/iqn.ronnie.test/1,if=none,id=MyISCSI Note, you can currently not boot a qemu guest from a scsi device. Note, This only works when the host is linux, since the emulation relies on definitions of SG_IO from the scsi-generic implementation in the linux kernel. It should be fairly easy to re-implement some structures similar enough for non-linux hosts to do the same style of passthrough via a fake scsi generic layer and libiscsi if need be. Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-06-24raw-posix: Fix build without is_allocated supportKevin Wolf
Move the declaration of s into the #ifdef sections that actually make use of it. Signed-off-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: Alexander Graf <agraf@suse.de>
2012-06-15qcow2: fix autoclear image header updateStefan Hajnoczi
The autoclear feature bits can be used for qcow2 file format features that are safe to "drop" by old programs that do not understand the feature. Upon opening the image file unknown autoclear feature bits are cleared and the image file header is rewritten, but this was happening too early in the code when critical header fields were not yet loaded. Process autoclear feature bits after all necessary header information has been loaded. Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15qcow2: Fix avail_sectors in cluster allocation codeKevin Wolf
avail_sectors should really be the number of sectors from the start of the allocation, not from the start of the write request. We're lucky enough that this mistake didn't cause any real bug. avail_sectors is only used in the intialiser of QCowL2Meta: .nb_available = MIN(requested_sectors, avail_sectors), m->nb_available in turn is only used for COW at the end of the allocation. A COW occurs only if the request wasn't cluster aligned, which in turn would imply that requested_sectors was less than avail_sectors (both in the original and in the fixed version). In this case avail_sectors is ignored and therefore the mistake doesn't cause any misbehaviour. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15qcow2: Simplify calculation for COW area at the endKevin Wolf
copy_sectors() always uses the sum (cluster_offset + n_start) or (start_sect + n_start), so if some value is added to both cluster_offset and start_sect, and subtracted from n_start, it's cancelled out anyway. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15qcow2: always operate caches in writeback modePaolo Bonzini
Writethrough does not need special-casing anymore in the qcow2 caches. The block layer adds flushes after every guest-initiated data write, and these will also flush the qcow2 caches to the OS. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15sheepdog: add coroutine_fn markers to coroutine functionsMORITA Kazutaka
Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15rbd: hook up cache optionsJosh Durgin
Writeback caching was added in Ceph 0.46, and writethrough will be in 0.47. These are controlled by general config options, so there's no need to check for librbd version. Signed-off-by: Josh Durgin <josh.durgin@inktank.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15qcow2: Support for fixing refcount inconsistenciesKevin Wolf
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15qemu-img check: Print fixed clusters and recheckKevin Wolf
When any inconsistencies have been fixed, print the statistics and run another check to make sure everything is correct now. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15qemu-img check -r for repairing imagesKevin Wolf
The QED block driver already provides the functionality to not only detect inconsistencies in images, but also fix them. However, this functionality cannot be manually invoked with qemu-img, but the check happens only automatically during bdrv_open(). This adds a -r switch to qemu-img check that allows manual invocation of an image repair. Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15stream: move rate limiting to a separate header filePaolo Bonzini
Make the code reusable. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15stream: move is_allocated_above to block.cPaolo Bonzini
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15stream: tweak usage of bdrv_co_is_allocatedPaolo Bonzini
is_allocated_base has complex semantics that are not really usable outside streaming. Split the check in two parts, where the allocated state for the top bs is moved to the caller. The resulting function is more generally useful. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15block: implement is_allocated for rawPaolo Bonzini
Either FIEMAP, or SEEK_DATA+SEEK_HOLE can be used to implement the is_allocated callback for raw files. On Linux ext4, btrfs and XFS all support it. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15qcow2: fix endianness conversionZhi Yong Wu
Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com> Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15qcow2: remove a line of unnecessary codeZhi Yong Wu
Commit 3948d1d4 removed the pointer argument we filled in with l2_offset but forgot to remove the unnecessary l2_offset assignment. Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com> Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-06-15qcow2: Silence false warningKevin Wolf
Some gcc versions seem not to be able to figure out that the switch statement covers all possible values and that c is therefore always initialised. Add a default branch for them. Reported-by: malc <av1474@comtv.ru> Signed-off-by: Kevin Wolf <kwolf@redhat.com> Signed-off-by: malc <av1474@comtv.ru>
2012-06-11cleanup qemu_co_sendv(), qemu_co_recvv() and friendsMichael Tokarev
The same as for non-coroutine versions in previous patches: rename arguments to be more obvious, change type of arguments from int to size_t where appropriate, and use common code for send and receive paths (with one extra argument) since these are exactly the same. Use common iov_send_recv() directly. qemu_co_sendv(), qemu_co_recvv(), and qemu_co_recv() are now trivial #define's merely adding one extra arg. qemu_co_sendv() and qemu_co_recvv() callers are converted to different argument order and extra `iov_cnt' argument. Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-06-11change qemu_iovec_to_buf() to match other to,from_buf functionsMichael Tokarev
It now allows specifying offset within qiov to start from and amount of bytes to copy. Actual implementation is just a call to iov_to_buf(). Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-06-11consolidate qemu_iovec_copy() and qemu_iovec_concat() and make them consistentMichael Tokarev
qemu_iovec_concat() is currently a wrapper for qemu_iovec_copy(), use the former (with extra "0" arg) in a few places where it is used. Change skip argument of qemu_iovec_copy() from uint64_t to size_t, since size of qiov itself is size_t, so there's no way to skip larger sizes. Rename it to soffset, to make it clear that the offset is applied to src. Also change the only usage of uint64_t in hw/9pfs/virtio-9p.c, in v9fs_init_qiov_from_pdu() - all callers of it actually uses size_t too, not uint64_t. One added restriction: as for all other iovec-related functions, soffset must point inside src. Order of argumens is already good: qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, int c, size_t bytes) vs: qemu_iovec_concat(QEMUIOVector *dst, QEMUIOVector *src, size_t soffset, size_t sbytes) (note soffset is after _src_ not dst, since it applies to src; for memset it applies to qiov). Note that in many places where this function is used, the previous call is qemu_iovec_reset(), which means many callers actually want copy (replacing dst content), not concat. So we may want to add a wrapper like qemu_iovec_copy() with the same arguments but which calls qemu_iovec_reset() before _concat(). Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-06-11allow qemu_iovec_from_buffer() to specify offset from which to start copyingMichael Tokarev
Similar to qemu_iovec_memset(QEMUIOVector *qiov, size_t offset, int c, size_t bytes); the new prototype is: qemu_iovec_from_buf(QEMUIOVector *qiov, size_t offset, const void *buf, size_t bytes); The processing starts at offset bytes within qiov. This way, we may copy a bounce buffer directly to a middle of qiov. This is exactly the same function as iov_from_buf() from iov.c, so use the existing implementation and rename it to qemu_iovec_from_buf() to be shorter and to match the utility function. As with utility implementation, we now assert that the offset is inside actual iovec. Nothing changed for current callers, because `offset' parameter is new. While at it, stop using "bounce-qiov" in block/qcow2.c and copy decrypted data directly from cluster_data instead of recreating a temp qiov for doing that. Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-06-11consolidate qemu_iovec_memset{,_skip}() into single function and use ↵Michael Tokarev
existing iov_memset() This patch combines two functions into one, and replaces the implementation with already existing iov_memset() from iov.c. The new prototype of qemu_iovec_memset(): size_t qemu_iovec_memset(qiov, size_t offset, int fillc, size_t bytes) It is different from former qemu_iovec_memset_skip(), and I want to make other functions to be consistent with it too: first how much to skip, second what, and 3rd how many of it. It also returns actual number of bytes filled in, which may be less than the requested `bytes' if qiov is smaller than offset+bytes, in the same way iov_memset() does. While at it, use utility function iov_memset() from iov.h in posix-aio-compat.c, where qiov was used. Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
2012-06-07build: move block/ objects to nested Makefile.objsPaolo Bonzini
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2012-05-30block: prevent snapshot mode $TMPDIR symlink attackJim Meyering
In snapshot mode, bdrv_open creates an empty temporary file without checking for mkstemp or close failure, and ignoring the possibility of a buffer overrun given a surprisingly long $TMPDIR. Change the get_tmp_filename function to return int (not void), so that it can inform its two callers of those failures. Also avoid the risk of buffer overrun and do not ignore mkstemp or close failure. Update both callers (in block.c and vvfat.c) to propagate temp-file-creation failure to their callers. get_tmp_filename creates and closes an empty file, while its callers later open that presumed-existing file with O_CREAT. The problem was that a malicious user could provoke mkstemp failure and race to create a symlink with the selected temporary file name, thus causing the qemu process (usually root owned) to open through the symlink, overwriting an attacker-chosen file. This addresses CVE-2012-2652. http://bugzilla.redhat.com/CVE-2012-2652 Signed-off-by: Jim Meyering <meyering@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-30sheepdog: fix return value of do_load_save_vm_stateMORITA Kazutaka
bdrv_save_vmstate and bdrv_load_vmstate should return the vmstate size on success, and -errno on error. Signed-off-by: MORITA Kazutaka <morita.kazutaka@lab.ntt.co.jp> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
2012-05-29Merge remote-tracking branch 'kwolf/for-anthony' into stagingAnthony Liguori
* kwolf/for-anthony: fdc-test: introduced qtest no_media_on_start and cmos qtest for floppy fdc: fix media detection fdc: floppy drive should be visible after start without media qemu-iotests: mark 035 qcow2-only qcow2: Check qcow2_alloc_clusters_at() return value sheepdog: use heap instead of stack for BDRVSheepdogState sheepdog: return -errno on error sheepdog: mark image as snapshot when tag is specified qemu-img: Explain how rebase operation can be used to perform a 'diff' operation. qcow2: don't leak buffer for unexpected qcow_version in header
2012-05-28ISCSI: Switch to using READ16/WRITE16 for I/O to the LUNRonnie Sahlberg
This allows using LUNs bigger than 2TB. Keep using READ10 for other device types such as MMC. Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
2012-05-28ISCSI: Only call READCAPACITY16 for SBC devices, use READCAPACITY10 for MMCRonnie Sahlberg
Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>