On Thu, Feb 14, 2013 at 07:21:27PM -0500, Tom Lane wrote: > Bruce Momjian <br...@momjian.us> writes: > > Agreed. The attached patch modifies pg_check_dir() to report about > > invisible and lost+found directory entries, and give more helpful > > messages to the user. > > I'm not terribly thrilled with special-casing 'lost+found' like that, > since it's an extremely filesystem-dependent thing that even today > probably only applies to a minority of our installed platforms. > > The special case for dotfiles might be useful, not because of any > connection to mount points but just because someone might forget > that such could be lurking in a directory that "looks empty".
I was ready to give up on this patch, but then I thought, what percentage does lost+found and dot-file-only directories cover for mount points? What other cases are there? This updated version of the patch reports about dot files if they are the _only_ files in the directory, and it suggests a top-level mount point might be the cause. Does this help? -- Bruce Momjian <br...@momjian.us> http://momjian.us EnterpriseDB http://enterprisedb.com + It's impossible for everything to be true. +
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c new file mode 100644 index 2ea3f6e..b8faf9c *** a/src/bin/initdb/initdb.c --- b/src/bin/initdb/initdb.c *************** void setup_signals(void); *** 257,262 **** --- 257,263 ---- void setup_text_search(void); void create_data_directory(void); void create_xlog_symlink(void); + void warn_on_mount_point(int error); void initialize_data_directory(void); *************** setup_signals(void) *** 3144,3150 **** void create_data_directory(void) { ! switch (pg_check_dir(pg_data)) { case 0: /* PGDATA not there, must create it */ --- 3145,3153 ---- void create_data_directory(void) { ! int ret; ! ! switch ((ret = pg_check_dir(pg_data))) { case 0: /* PGDATA not there, must create it */ *************** create_data_directory(void) *** 3179,3193 **** break; case 2: /* Present and not empty */ fprintf(stderr, _("%s: directory \"%s\" exists but is not empty\n"), progname, pg_data); ! fprintf(stderr, ! _("If you want to create a new database system, either remove or empty\n" ! "the directory \"%s\" or run %s\n" ! "with an argument other than \"%s\".\n"), ! pg_data, progname, pg_data); exit(1); /* no further message needed */ default: --- 3182,3201 ---- break; case 2: + case 3: + case 4: /* Present and not empty */ fprintf(stderr, _("%s: directory \"%s\" exists but is not empty\n"), progname, pg_data); ! if (ret != 4) ! warn_on_mount_point(ret); ! else ! fprintf(stderr, ! _("If you want to create a new database system, either remove or empty\n" ! "the directory \"%s\" or run %s\n" ! "with an argument other than \"%s\".\n"), ! pg_data, progname, pg_data); exit(1); /* no further message needed */ default: *************** create_xlog_symlink(void) *** 3206,3211 **** --- 3214,3220 ---- if (strcmp(xlog_dir, "") != 0) { char *linkloc; + int ret; /* clean up xlog directory name, check it's absolute */ canonicalize_path(xlog_dir); *************** create_xlog_symlink(void) *** 3216,3222 **** } /* check if the specified xlog directory exists/is empty */ ! switch (pg_check_dir(xlog_dir)) { case 0: /* xlog directory not there, must create it */ --- 3225,3231 ---- } /* check if the specified xlog directory exists/is empty */ ! switch ((ret = pg_check_dir(xlog_dir))) { case 0: /* xlog directory not there, must create it */ *************** create_xlog_symlink(void) *** 3255,3268 **** break; case 2: /* Present and not empty */ fprintf(stderr, _("%s: directory \"%s\" exists but is not empty\n"), progname, xlog_dir); ! fprintf(stderr, ! _("If you want to store the transaction log there, either\n" ! "remove or empty the directory \"%s\".\n"), ! xlog_dir); exit_nicely(); default: --- 3264,3282 ---- break; case 2: + case 3: + case 4: /* Present and not empty */ fprintf(stderr, _("%s: directory \"%s\" exists but is not empty\n"), progname, xlog_dir); ! if (ret != 4) ! warn_on_mount_point(ret); ! else ! fprintf(stderr, ! _("If you want to store the transaction log there, either\n" ! "remove or empty the directory \"%s\".\n"), ! xlog_dir); exit_nicely(); default: *************** create_xlog_symlink(void) *** 3291,3296 **** --- 3305,3325 ---- } + void + warn_on_mount_point(int error) + { + if (error == 2) + fprintf(stderr, + _("It contains a dot-prefixed/invisible file, perhaps due to it being a mount point.\n")); + else if (error == 3) + fprintf(stderr, + _("It contains a lost+found directory, perhaps due to it being a mount point.\n")); + + fprintf(stderr, + _("Using the top-level directory of a mount point is not recommended.\n")); + } + + void initialize_data_directory(void) { diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c new file mode 100644 index b6f7744..fb5a1bd *** a/src/bin/pg_basebackup/pg_basebackup.c --- b/src/bin/pg_basebackup/pg_basebackup.c *************** verify_dir_is_empty_or_create(char *dirn *** 371,376 **** --- 371,378 ---- */ return; case 2: + case 3: + case 4: /* * Exists, not empty diff --git a/src/port/pgcheckdir.c b/src/port/pgcheckdir.c new file mode 100644 index 3b8258c..aee5997 *** a/src/port/pgcheckdir.c --- b/src/port/pgcheckdir.c *************** pg_check_dir(const char *dir) *** 31,36 **** --- 31,37 ---- int result = 1; DIR *chkdir; struct dirent *file; + bool dot_found = false; errno = 0; *************** pg_check_dir(const char *dir) *** 47,61 **** /* skip this and parent directory */ continue; } else { ! result = 2; /* not empty */ break; } } #ifdef WIN32 - /* * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in * released version --- 48,73 ---- /* skip this and parent directory */ continue; } + #ifndef WIN32 + /* file starts with "." */ + else if (file->d_name[0] == '.') + { + dot_found = true; + } + else if (strcmp("lost+found", file->d_name) == 0) + { + result = 3; /* not empty, mount point */ + break; + } + #endif else { ! result = 4; /* not empty */ break; } } #ifdef WIN32 /* * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in * released version *************** pg_check_dir(const char *dir) *** 69,73 **** --- 81,89 ---- if (errno != 0) result = -1; /* some kind of I/O error? */ + /* We report on dot-files if we _only_ find dot files */ + if (result == 1 && dot_found) + result = 2; + return result; }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers