On Tue, Feb 5, 2013 at 08:49:17AM -0500, Peter Eisentraut wrote:
> On 2/5/13 7:32 AM, Kevin Grittner wrote:
> > Sean Chittenden <[email protected]> wrote:
> >
> >> > Currently src/port/pgcheckdir.c will reject non-empty
> >> > directories, which is an issue during initdb(1) when PGDATA is
> >> > also the mount point for filesystems that support snapshots (e.g.
> >> > ZFS or UFS2).
> >> > Granted it's not hard to create a subdirectory, initdb there and
> >> > move the contents of the files around, it's extra work that
> >> > shouldn't be required.
> > I feel that it is very bad practice to use the mount point as the
> > PGDATA directory. It forcloses a lot of reasonable actions that
> > someone managing the database server might want to take.
>
> Yes, a variant of this particular patch gets rejected about once every
> 18 months.
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.
--
Bruce Momjian <[email protected]> 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..03eadcd
*** a/src/bin/initdb/initdb.c
--- b/src/bin/initdb/initdb.c
*************** setup_signals(void)
*** 3144,3150 ****
void
create_data_directory(void)
{
! switch (pg_check_dir(pg_data))
{
case 0:
/* PGDATA not there, must create it */
--- 3144,3152 ----
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:
--- 3181,3205 ----
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 == 2)
! fprintf(stderr,
! _("It contains a dot-prefixed/invisible file.\n"));
! else if (ret == 3)
! fprintf(stderr,
! _("It contains a lost+found directory.\n"
! "Using the top-level directory of a mount point is not recommended.\n"));
! if (ret != 3)
! 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 ****
--- 3218,3224 ----
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 */
--- 3229,3235 ----
}
/* 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:
--- 3268,3291 ----
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 == 2)
! fprintf(stderr,
! _("It contains a dot-prefixed/invisible file.\n"));
! else if (ret == 3)
! fprintf(stderr,
! _("It contains a lost+found directory.\n"
! "Using the top-level directory of a mount point is not recommended.\n"));
! if (ret != 3)
! 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:
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..9d6f216
*** a/src/port/pgcheckdir.c
--- b/src/port/pgcheckdir.c
*************** pg_check_dir(const char *dir)
*** 47,55 ****
/* skip this and parent directory */
continue;
}
else
{
! result = 2; /* not empty */
break;
}
}
--- 47,68 ----
/* skip this and parent directory */
continue;
}
+ #ifndef WIN32
+ /* file starts with "." */
+ else if (file->d_name[0] == '.')
+ {
+ result = 2; /* not empty, invisible file */
+ break;
+ }
+ else if (strcmp("lost+found", file->d_name) == 0)
+ {
+ result = 3; /* not empty, mount point */
+ break;
+ }
+ #endif
else
{
! result = 4; /* not empty */
break;
}
}
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers