#include <sys/mount.h>
#include <mntent.h>
#include <getopt.h>
-#include <sys/utsname.h>
#include "obdctl.h"
#include <lustre_ver.h>
#include <glob.h>
+#include <ctype.h>
+#include <limits.h>
+#include <mount_utils.h>
#define MAX_HW_SECTORS_KB_PATH "queue/max_hw_sectors_kb"
#define MAX_SECTORS_KB_PATH "queue/max_sectors_kb"
int nomtab = 0;
int fake = 0;
int force = 0;
-static char *progname = NULL;
+char *progname = NULL;
void usage(FILE *out)
{
"\t<mntopt>: one or more comma separated of:\n"
"\t\t(no)flock,(no)user_xattr,(no)acl\n"
"\t\tnosvc: only start MGC/MGS obds\n"
+ "\t\tnomgs: only start target obds, using existing MGS\n"
"\t\texclude=<ostname>[:<ostname>] : colon-separated list of "
"inactive OSTs (e.g. lustre-OST0001)\n"
);
{ "nosuid", 0, MS_NOSUID }, /* don't honor suid executables */
{ "dev", 1, MS_NODEV }, /* interpret device files */
{ "nodev", 0, MS_NODEV }, /* don't interpret devices */
+ { "sync", 0, MS_SYNCHRONOUS}, /* synchronous I/O */
{ "async", 1, MS_SYNCHRONOUS}, /* asynchronous I/O */
+ { "atime", 1, MS_NOATIME }, /* set file access time on read */
+ { "noatime", 0, MS_NOATIME }, /* do not set file access time on read */
+#ifdef MS_NODIRATIME
+ { "diratime", 1, MS_NODIRATIME }, /* set file access time on read */
+ { "nodiratime",0,MS_NODIRATIME }, /* do not set file access time on read */
+#endif
+#ifdef MS_RELATIME
+ { "relatime", 0, MS_RELATIME }, /* set file access time on read */
+ { "norelatime",1,MS_RELATIME }, /* do not set file access time on read */
+#endif
{ "auto", 0, 0 }, /* Can be mounted using -a */
{ "noauto", 0, 0 }, /* Can only be mounted explicitly */
{ "nousers", 1, 0 }, /* Forbid ordinary user to mount */
{ "nouser", 1, 0 }, /* Forbid ordinary user to mount */
{ "noowner", 1, 0 }, /* Device owner has no special privs */
{ "_netdev", 0, 0 }, /* Device accessible only via network */
+ { "loop", 0, 0 },
{ NULL, 0, 0 }
};
/****************************************************************************/
struct stat stat_buf;
char *chk_major, *chk_minor;
char *savept, *dev, *s2 = 0;
- char buf[PATH_MAX], path[PATH_MAX];
+ char *ret_path;
+ char buf[PATH_MAX] = {'\0'}, path[PATH_MAX] = {'\0'};
+ char real_path[PATH_MAX] = {'\0'};
int i, rc = 0;
int major, minor;
if (!source)
return -EINVAL;
- if (strncmp(source, "/dev/loop", 9) == 0)
+ ret_path = realpath(source, real_path);
+ if (ret_path == NULL) {
+ if (verbose)
+ fprintf(stderr, "warning: %s: cannot resolve: %s",
+ source, strerror(errno));
+ return -EINVAL;
+ }
+
+ src_len = sizeof(real_path);
+
+ if (strncmp(real_path, "/dev/loop", 9) == 0)
return 0;
- if ((*source != '/') && ((s2 = strpbrk(source, ",:")) != NULL))
+ if ((real_path[0] != '/') && ((s2 = strpbrk(real_path, ",:")) != NULL))
return 0;
- dev = source + src_len - 1;
- while (dev > source && (*dev != '/')) {
+ dev = real_path + src_len - 1;
+ while (dev > real_path && (*dev != '/')) {
if (isdigit(*dev))
*dev = 0;
dev--;
* match any entry under /sys/block/. In that case we need to
* match the major/minor number to find the entry under
* sys/block corresponding to /dev/X */
- dev = source + src_len - 1;
- while (dev > source) {
+ dev = real_path + src_len - 1;
+ while (dev > real_path) {
if (isdigit(*dev))
*dev = 0;
dev--;
rc = stat(dev, &stat_buf);
if (rc) {
- fprintf(stderr, "warning: %s, device %s stat failed\n",
- strerror(errno), dev);
+ if (verbose)
+ fprintf(stderr, "warning: %s, device %s stat failed\n",
+ strerror(errno), dev);
return rc;
}
minor = minor(stat_buf.st_rdev);
rc = glob("/sys/block/*", GLOB_NOSORT, NULL, &glob_info);
if (rc) {
- fprintf(stderr, "warning: failed to read entries under "
- "/sys/block\n");
+ if (verbose)
+ fprintf(stderr, "warning: failed to read entries under "
+ "/sys/block\n");
return rc;
}
if (i == glob_info.gl_pathc) {
if (verbose)
fprintf(stderr,"warning: device %s does not match any "
- "entry under /sys/block\n", source);
- return -EINVAL;
+ "entry under /sys/block\n", real_path);
+ rc = -EINVAL;
+ goto out;
}
snprintf(path, sizeof(path), "%s/%s", glob_info.gl_pathv[i],
if (verbose)
fprintf(stderr, "warning: opening %s: %s\n",
path, strerror(errno));
- return rc;
+ goto out;
}
if (strlen(buf) - 1 > 0) {
fprintf(stderr, "warning: writing to %s: %s\n",
path, strerror(errno));
}
+
+out:
+ globfree(&glob_info);
return rc;
}
if (verbose) {
for (i = 0; i < argc; i++)
printf("arg[%d] = %s\n", i, argv[i]);
- printf("source = %s (%s), target = %s\n", usource, source, target);
+ printf("source = %s (%s), target = %s\n", usource, source,
+ target);
printf("options = %s\n", orig_options);
}
if (set_tunables(source, strlen(source)) && verbose)
fprintf(stderr, "%s: unable to set tunables for %s"
- " (may cause reduced IO performance)",
+ " (may cause reduced IO performance)\n",
argv[0], source);
+ register_service_tags(usource, source, target);
+
if (!fake)
/* flags and target get to lustre_get_sb, but not
lustre_fill_super. Lustre ignores the flags, but mount