Re: Using fsync() to synchronize a USB mass storage device failed

From: Andrew Morton
Date: Sat Feb 25 2006 - 06:53:11 EST


Christian Neumair <chris@xxxxxxxxxxxx> wrote:
>
> I've seen various postings on the lkml on the issue of fsync()ing block
> devices and the expected behavior. Some claim that fsync()ing the mount
> point of a block device will flush its buffers, a HOWTO I read claims
> that one has to apply it to the device node, because it is the
> representation of the block device.
>
> The POSIX standard demands [1]:
>
> "The fsync() function shall request that all data for the open file
> descriptor named by fildes is to be transferred to the storage device
> associated with the file described by fildes."
>
> To my interpretation this means that all buffers of a mass storage
> device should be flushed when calling fsync() on its file
> representation, i.e. /dev/foo.
>
> I've tried various Ubuntu-packaged kernel releases (2.6.12 and later),
> and none of it seems to actually assert that the data is written when
> using code like
>
> int fd = open ("/dev/sdb1", O_RDONLY); /* I also tried O_WRONLY */
>
> or
>
> int fd = open ("/media/usbdisk", O_DIRECTORY | O_RDONLY);
>
> and then doing
>
> fsync (fd);
> close (fd);
>
> Unfortunately, none of the code really blocked until the whole buffer
> was written, and a diode on the mass storage indicated that data was
> still being written to it after my testing application terminated, while
> for a simple sync() call (or "sync" program invocation) the whole
> process really blocked until the data was on disk, as proven by the
> non-flashing diode.
>
> I haven't investigated the code in detail, but fs/buffer.c suggests that
> sync_inodes is invoked on sync() but not on fsync(), and the latter does
> not lookup the block device the file refers to, thus not ensuring that
> fsync_bdev() is called on it.
>
> If you wonder why this is needed - over at GNOME we're having issues
> where USB sticks are unmounted and the users have no clue when it's
> ready to be removed [1]. We'd like to fsync() in a thread and tell the
> users that an unmount operation is going on and still needs some time.
> Because there may be multiple storage device attached, it isn't a good
> idea to sync() all devices, but just that one which is about to be
> ejected.
>
>
> [1] http://www.opengroup.org/onlinepubs/009695399/functions/fsync.html
> [2] http://bugzilla.gnome.org/show_bug.cgi?id=329098

It works for me. Using
http://www.zip.com.au/~akpm/linux/patches/stuff/ext3-tools.tar.gz:

sleep 10000 < /dev/hda5 & # Keep bdev open - coz last close() syncs it

# This doesn't sync the device:
write-and-fsync -m 20 /dev/hda5 ; read-and-fsync -m 20 /dev/hda5

# This does:
write-and-fsync -m 20 /dev/hda5 ; read-and-fsync -f -m 20 /dev/hda5

It's a bit odd to do an fsync() on an O_RDONLY fd, but it does the fsync.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/