#include <sys/mount.h>
#include <linux/types.h>
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
+#endif
+
#ifdef VERSION
# define PU_VERSION VERSION
#else
static const char pu_version[] = PU_VERSION;
static bool pu_debug;
-#define ARRAY_SIZE(a) ((sizeof(a)) / (sizeof((a)[0])))
+enum {
+ PU_DEF_SCAN_COUNT_MAX = 10,
+ PU_DEF_SIGNAL = SIGKILL, /* XXX Hard coded in help message. */
+ PU_EXIT_SUCCESS = 0, /* See the help message. */
+ PU_EXIT_PROCESSES_REMAINED = 1,
+ PU_EXIT_FAILURE = 2,
+ PU_EXIT_TRY_HELP = 3,
+ PU_FILEID_LUSTRE = 0x97, /* From linux/exportfs.h */
+ PU_FILEID_INVALID = 0xff, /* ... */
+ PU_MOUNT_ID_FAKE = INT_MAX,
+};
+
+struct pu_fid {
+ __u64 f_seq;
+ __u32 f_oid;
+ __u32 f_ver;
+};
+
+struct pu_lustre_nfs_fid {
+ struct pu_fid lnf_child;
+ struct pu_fid lnf_parent;
+};
#define PU_DEBUG(fmt, args...) \
do { \
#define PU_FATAL(fmt, args...) \
do { \
- PU_ERROR("fatal: "fmt, ##args); \
- exit(EXIT_FAILURE); \
+ PU_ERROR("fatal: "fmt, ##args); \
+ exit(PU_EXIT_FAILURE); \
} while (0)
#define OOM() \
do { \
fprintf(stderr, \
"Try '%s --help' for more information.\n", \
- pu_program_name); \
- exit(2); \
+ pu_program_name); \
+ exit(PU_EXIT_TRY_HELP); \
} while (0)
#define TRY_HELP(fmt, args...) \
return rc;
}
-struct pu_fid {
- __u64 f_seq;
- __u32 f_oid;
- __u32 f_ver;
-};
-
-struct pu_lustre_nfs_fid {
- struct pu_fid lnf_child;
- struct pu_fid lnf_parent;
-};
-
-enum {
- PU_MOUNT_ID_FAKE = INT_MAX,
- PU_FILEID_LUSTRE = 0x97, /* From linux/exportfs.h */
- PU_FILEID_INVALID = 0xff, /* ... */
-};
-
static int pu_name_to_handle(int dirfd, const char *path, struct file_handle **phandle, int *mount_id, int flags)
{
struct file_handle *handle = NULL;
{ NULL },
};
-void usage(void)
+static void print_help(void)
{
printf(
"Usage pumount [OPTION]... DIRECTORY\n"
" --no-open do not open DIRECTORY\n"
" --no-signal do not send signals\n"
" --no-umount do not unmount FS\n"
-" -p, --print print users of FS\n"
-" --scan-count=COUNT scan for users at most COUNT times\n" /* ... (default %d) */
-" --signal=SIG send SIG to users of FS (default SIGKILL)\n"
+" -p, --print print uses of FS\n"
+" --scan-count=COUNT scan for processes at most COUNT times (default %d)\n"
+" --signal=SIG send SIG to processes using FS (default SIGKILL)\n" /* XXX */
" --version print version information and exit\n"
"\n"
"Operation:\n"
"python 8942 0 lustre [0x200000404:0x3:0x0] /lustre/fs0a12/client/projects/EGGS\\040V7\\040FINAL.xls\n"
"\n"
"Exit status:\n"
-" 0 Unmount succeeded and no users remained.\n"
-" 1 Unmount failed or users remained or other error.\n"
-" 2 An invalid option or argument was supplied.\n");
-/* TODO (maybe) add more statuses about users remaining, minor errors. ... */
+" %d Unmount succeeded and no processes using FS remained.\n"
+" %d Unmount succeeded but one or more processes using FS remained.\n"
+" %d Unmount failed or some other major error occurred.\n"
+" %d An invalid option or argument was supplied.\n",
+PU_DEF_SCAN_COUNT_MAX,
+PU_EXIT_SUCCESS,
+PU_EXIT_PROCESSES_REMAINED,
+PU_EXIT_FAILURE,
+PU_EXIT_TRY_HELP
+);
}
int main(int argc, char *argv[])
bool do_print = false;
bool do_signal = true;
bool do_umount = true;
- int sig = SIGKILL;
+ int sig = PU_DEF_SIGNAL;
int umount2_flags = MNT_DETACH;
int proc_count;
- int scan_count_max = 4;
+ int scan_count_max = PU_DEF_SCAN_COUNT_MAX;
int scan_count;
int use_count = 0;
int err_count = 0;
umount2_flags |= MNT_FORCE;
break;
case 'h':
- usage();
- exit(EXIT_SUCCESS);
+ print_help();
+ exit(PU_EXIT_SUCCESS);
case 'l':
/* Already implied. */
break;
case PU_OPT_SCAN_COUNT:
rc = pu_strtoi(optarg, &scan_count_max, 0, INT_MAX);
if (rc < 0)
- PU_FATAL("invalid scan-count '%s'\n", optarg);
+ TRY_HELP("invalid scan-count '%s'\n", optarg);
break;
case PU_OPT_SIGNAL:
rc = pu_str_to_signal(optarg, &sig);
if (rc < 0)
- PU_FATAL("invalid signal '%s'\n", optarg);
+ TRY_HELP("invalid signal '%s'\n", optarg);
break;
case PU_OPT_VERSION:
printf("%s %s\n", pu_program_name, pu_version);
- exit(EXIT_SUCCESS);
+ exit(PU_EXIT_SUCCESS);
case '?':
TRY_HELP_1();
}
}
- if (optind + 1 != argc) {
+ if (optind + 1 != argc)
TRY_HELP("usage: %s [OPTION]... DIRECTORY\n",
pu_program_name);
- }
mount_point = argv[optind];
if (puc->puc_use_count == 0)
goto next;
- PU_DEBUG("found process %d, comm '%s' with %d usesN of mount %d\n",
+ PU_DEBUG("found process %d, comm '%s' with %d uses of mount %d\n",
pid, puc_comm(puc), puc->puc_use_count, mount_id);
proc_count += 1;
proc_count, proc_count == 1 ? "" : "es",
mount_point, mount_id,
scan_count, scan_count == 1 ? "" : "s");
- status = EXIT_FAILURE;
+ status = PU_EXIT_PROCESSES_REMAINED;
} else {
- status = EXIT_SUCCESS;
+ status = PU_EXIT_SUCCESS;
}
+ PU_DEBUG_D(status);
+
/* If there are no other users of FS then the real umount
* should happen in the close of mount_dirfd. */
pu_close(&mount_dirfd);