Re: O_NOATIME ?

2016-10-26 Thread Theodore Ts'o
On Wed, Oct 26, 2016 at 11:46:50AM +0200, Paul Slootman wrote:
> Most filesystems on modern linux systems should be mounted with the
> relatime option.

This is the default...

> You can also use noatime as a mount option, but then be sure that no
> application uses the atimes of files; e.g. something like mutt use the
> atime and mtime to determine whether there is a mail file with unread
> mail.

With the latest Linux kernels (4.0+), there is also the "lazytime"
mount option.  This causes the kernel to avoid writing back inodes
that only have "dirty timestamps", until either (a) some other change
is made to the inode, (b) fsync(), syncfs(), or sync() is called, (c)
an undeleted inode is evicted from memory or the file system is
unounted, (d) 24 hours have gone by, or (e) in the case of ext4, if
some other change is made to an inode in the same inode table block as
an inode with a dirty timestamp (so we need to do the disk I/O
anyway).

With lazytime, the timestamp is updated in memory, so stat(2) will
always return the correct timestamp, and in normal practice, the
timestamps will be (eventually) updated on disk.  However if a
timestsamp gets updated multiple times --- for example, a database
file getting updated with O_DIRECT writes, instead of the mtime field
being written out every 30 seconds, we can defer the timestamp updates
and collapse them into a much smaller set of inode table block writes.

Cheers,

- Ted

-- 
Please use reply-all for most replies to avoid omitting the mailing list.
To unsubscribe or change options: https://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Feature request: preallocation of directories

2008-09-01 Thread Theodore Ts'o
Hi there,

One of the things that I've been doing for fun is to try to speed up
ext4's fsck time.  As you can see here:

   http://thunk.org/tytso/blog/2008/08/08/fast-ext4-fsck-times/

Fsck'ing an ext4 filesystem can be between 6-8 times after than the
equivalent file hierarchy on ext4.  In order to speed it up further, the
main place to look is in pass #2, where the directory is scanned, and in
order to do that, I need to address the problem of directory
fragmentation.

In the long run we probably should have an appropriate kernel interface
to support this (probably via the already-existing fallocate interface,
applied to directories, or an extension to the mkdir system call which
gives the anticipated size of the directory), but in the meantime,
userspace can expand a directory simply by creating some zero-length,
large filenames, and then deleting them.  But in order to do that,
programs like cpio, tar and rsync (regardless of the short-term
create-large- files-hack or some mkdir extension), need to be involved
since they know how big the filesystem will likely be.

So what I am interested in trying to prototype is a new option to rsync
which, if it needs to create a directory, will take the size of the
directory on the source and fill it with dummy files with large
filenames (which are then deleted after the directory is expanded).  I
have a program which does this separately, but while this makes the
makes the directories nicely contiguous on disk, the block
allocation suffers, since the directories aren't created in the correct
block groups given that they are created first, instead of as the
files are copied over.  

Unfortunately, being new to rsync's source code, it's not clear to me
how is the best way to add this feature.  I was hoping that some rsync
hacker with some free time would either take a tiny bit of code for the
attached copy_dirstruct.c program and add it to rsync in the appropriate
place, or give me some tips about how to add it.  I *think* it is in
generator.c, but recv_generator is complicated enough that I'm not
entirely confident how to add it without breaking some other option, or
some part of its functioning.

- Ted

/*
 * copy_dirstruct.c - Copy a directory structure
 *
 * Compile using: cc -o copy_dirstruct copy_dirstruct -le2p -lcom_err 
 *
 * Copyright (C) 2008 Theodore Ts'o [EMAIL PROTECTED]
 *
 * This file can be redistributed under the terms of the GNU General
 * Public License.
 */

#include sys/types.h
#include dirent.h
#include fcntl.h
#include stdio.h
#include stdlib.h
#include unistd.h
#include string.h
#include errno.h
#include sys/param.h
#include sys/stat.h
#include ext2fs/ext2_fs.h

#ifdef __GNUC__
#define EXT2FS_ATTR(x) __attribute__(x)
#else
#define EXT2FS_ATTR(x)
#endif

#ifndef S_ISLNK /* So we can compile even with gcc-warn */
# ifdef __S_IFLNK
#  define S_ISLNK(mode)  __S_ISTYPE((mode), __S_IFLNK)
# else
#  define S_ISLNK(mode)  0
# endif
#endif

#include et/com_err.h
#include e2p/e2p.h

static const char * program_name = copy_dirstruct;

#ifdef _LFS64_LARGEFILE
#define LSTAT   lstat64
#define STRUCT_STAT struct stat64
#else
#define LSTAT   lstat
#define STRUCT_STAT struct stat
#endif

const char *dest_dir = /mnt;
const char *src_dir = /;
int blocksize = 4096;
int dest_len = 4;
int silent = 0;
dev_t xdev;

static void usage(void)
{
fprintf(stderr,
Usage: %s [-RVf] [-+=AacDdijsSu] [-v version] files...\n,
program_name);
exit(1);
}

static int copy_dir_proc(const char *, struct dirent *, void *);

static int copy_dir(const char * name)
{
unsigned long flags;
struct stat st;
char*newname;
off_t   size;
charfill[250];
int i, l, fd, num;
int recurse;

if (LSTAT (name, st) == -1) {
if (!silent)
com_err (program_name, errno,
 while trying to stat %s, name);
return -1;
}

if (!S_ISDIR(st.st_mode))
return 0;

recurse = (st.st_dev == xdev);

newname = malloc(strlen(name) + dest_len + 2);
if (!newname) {
if (!silent)
com_err(program_name, 0, couldn't allocate newname);
return -1;
}
sprintf(newname, %s/%s, dest_dir, name);

size = st.st_size;

if (mkdir(newname, st.st_mode)  0) {
if (errno == EEXIST) {
if (stat(newname, st) == 0 
S_ISDIR(st.st_mode))
goto dir_ok;
errno = EEXIST;
}
if (!silent)
com_err(program_name, errno, 
while trying to mkdir %s