Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F1842032
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c
index daef2f369..4a6665cfb 100644
--- a/gfs2/libgfs2/misc.c
+++ b/gfs2/libgfs2/misc.c
@@ -1,700 +1,700 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <sys/mount.h>
#include <linux/types.h>
#include <sys/file.h>
#include <dirent.h>
#include <linux/kdev_t.h>
#include <sys/sysmacros.h>
#include "libgfs2.h"
#define PAGE_SIZE (4096)
static char sysfs_buf[PAGE_SIZE];
void
compute_constants(struct gfs2_sbd *sdp)
{
uint32_t hash_blocks, ind_blocks, leaf_blocks;
uint32_t tmp_blocks;
unsigned int x;
sdp->md.next_inum = 1;
sdp->sd_sb.sb_bsize_shift = ffs(sdp->bsize) - 1;
sdp->sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sdp->bsize;
sdp->sd_fsb2bb_shift = sdp->sd_sb.sb_bsize_shift -
GFS2_BASIC_BLOCK_SHIFT;
sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
sdp->sd_diptrs = (sdp->bsize - sizeof(struct gfs2_dinode)) /
sizeof(uint64_t);
sdp->sd_inptrs = (sdp->bsize - sizeof(struct gfs2_meta_header)) /
sizeof(uint64_t);
sdp->sd_jbsize = sdp->bsize - sizeof(struct gfs2_meta_header);
sdp->sd_hash_bsize = sdp->bsize / 2;
sdp->sd_hash_bsize_shift = sdp->sd_sb.sb_bsize_shift - 1;
sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
/* Compute maximum reservation required to add a entry to a directory */
hash_blocks = DIV_RU(sizeof(uint64_t) * (1 << GFS2_DIR_MAX_DEPTH),
sdp->sd_jbsize);
ind_blocks = 0;
for (tmp_blocks = hash_blocks; tmp_blocks > sdp->sd_diptrs;) {
tmp_blocks = DIV_RU(tmp_blocks, sdp->sd_inptrs);
ind_blocks += tmp_blocks;
}
leaf_blocks = 2 + GFS2_DIR_MAX_DEPTH;
sdp->sd_max_dirres = hash_blocks + ind_blocks + leaf_blocks;
sdp->sd_heightsize[0] = sdp->bsize - sizeof(struct gfs2_dinode);
sdp->sd_heightsize[1] = sdp->bsize * sdp->sd_diptrs;
for (x = 2;; x++) {
uint64_t space, d;
uint32_t m;
space = sdp->sd_heightsize[x - 1] * sdp->sd_inptrs;
d = space;
m = do_div(d, sdp->sd_inptrs);
if (d != sdp->sd_heightsize[x - 1] || m)
break;
sdp->sd_heightsize[x] = space;
}
sdp->sd_max_height = x;
if (sdp->sd_max_height > GFS2_MAX_META_HEIGHT)
die("bad constants (1)\n");
sdp->sd_jheightsize[0] = sdp->bsize - sizeof(struct gfs2_dinode);
sdp->sd_jheightsize[1] = sdp->sd_jbsize * sdp->sd_diptrs;
for (x = 2;; x++) {
uint64_t space, d;
uint32_t m;
space = sdp->sd_jheightsize[x - 1] * sdp->sd_inptrs;
d = space;
m = do_div(d, sdp->sd_inptrs);
if (d != sdp->sd_jheightsize[x - 1] || m)
break;
sdp->sd_jheightsize[x] = space;
}
sdp->sd_max_jheight = x;
if (sdp->sd_max_jheight > GFS2_MAX_META_HEIGHT)
die("bad constants (2)\n");
}
int
find_gfs2_meta(struct gfs2_sbd *sdp)
{
FILE *fp = fopen("/proc/mounts", "r");
char name[] = "gfs2meta";
char buffer[PATH_MAX];
char fstype[80], mfsoptions[PATH_MAX];
char meta_device[PATH_MAX];
char meta_path[PATH_MAX];
int fsdump, fspass;
if (fp == NULL) {
perror("open: /proc/mounts");
exit(EXIT_FAILURE);
}
sdp->metafs_mounted = FALSE;
memset(sdp->metafs_path, 0, sizeof(sdp->metafs_path));
memset(meta_path, 0, sizeof(meta_path));
while ((fgets(buffer, PATH_MAX - 1, fp)) != NULL) {
buffer[PATH_MAX - 1] = '\0';
if (strstr(buffer, name) == 0)
continue;
if (sscanf(buffer, "%s %s %s %s %d %d", meta_device,
meta_path, fstype,mfsoptions, &fsdump,
&fspass) != 6)
continue;
if (strcmp(meta_device, sdp->device_name) == 0 ||
strcmp(meta_device, sdp->path_name) == 0) {
fclose(fp);
sdp->metafs_mounted = FALSE;
strcpy(sdp->metafs_path, meta_path);
return TRUE;
}
}
fclose(fp);
return FALSE;
}
int
dir_exists(const char *dir)
{
int fd, ret;
struct stat statbuf;
fd = open(dir, O_RDONLY);
if (fd<0) {
if (errno == ENOENT)
return 0;
die("Couldn't open %s : %s\n", dir, strerror(errno));
}
ret = fstat(fd, &statbuf);
if (ret)
die("stat failed on %s : %s\n", dir, strerror(errno));
if (S_ISDIR(statbuf.st_mode)) {
close(fd);
return 1;
}
close(fd);
die("%s exists, but is not a directory. Cannot mount metafs here\n", dir);
}
void
check_for_gfs2(struct gfs2_sbd *sdp)
{
FILE *fp = fopen("/proc/mounts", "r");
char buffer[PATH_MAX];
char fstype[80];
int fsdump, fspass, ret;
char fspath[PATH_MAX];
char fsoptions[PATH_MAX];
char *realname;
realname = realpath(sdp->path_name, NULL);
if (!realname) {
perror(sdp->path_name);
return;
}
if (fp == NULL) {
perror("open: /proc/mounts");
exit(EXIT_FAILURE);
}
while ((fgets(buffer, PATH_MAX - 1, fp)) != NULL) {
buffer[PATH_MAX - 1] = 0;
if (strstr(buffer, "0") == 0)
continue;
if ((ret = sscanf(buffer, "%s %s %s %s %d %d",
sdp->device_name, fspath,
fstype, fsoptions, &fsdump, &fspass)) != 6)
continue;
if (strcmp(fstype, "gfs2") != 0)
continue;
/* Check if they specified the device instead of mnt point */
if (strcmp(sdp->device_name, realname) == 0)
strcpy(sdp->path_name, fspath); /* fix it */
else if (strcmp(fspath, realname) != 0)
continue;
fclose(fp);
if (strncmp(sdp->device_name, "/dev/loop", 9) == 0)
die("Cannot perform this operation on a loopback GFS2 mount.\n");
free(realname);
return;
}
free(realname);
fclose(fp);
die("gfs2 Filesystem %s is not mounted.\n", sdp->path_name);
}
void
mount_gfs2_meta(struct gfs2_sbd *sdp)
{
int ret;
/* mount the meta fs */
strcpy(sdp->metafs_path, "/tmp/.gfs2meta");
if (!dir_exists(sdp->metafs_path)) {
ret = mkdir(sdp->metafs_path, 0700);
if (ret)
die("Couldn't create %s : %s\n", sdp->metafs_path,
strerror(errno));
}
- ret = mount(sdp->device_name, sdp->metafs_path, "gfs2meta", 0, NULL);
+ ret = mount(sdp->path_name, sdp->metafs_path, "gfs2meta", 0, NULL);
if (ret)
die("Couldn't mount %s : %s\n", sdp->metafs_path,
strerror(errno));
}
void
lock_for_admin(struct gfs2_sbd *sdp)
{
int error;
if (sdp->debug)
printf("\nTrying to get admin lock...\n");
sdp->metafs_fd = open(sdp->metafs_path, O_RDONLY | O_NOFOLLOW);
if (sdp->metafs_fd < 0)
die("can't open %s: %s\n",
sdp->metafs_path, strerror(errno));
error = flock(sdp->metafs_fd, LOCK_EX);
if (error)
die("can't flock %s: %s\n", sdp->metafs_path, strerror(errno));
if (sdp->debug)
printf("Got it.\n");
}
void
cleanup_metafs(struct gfs2_sbd *sdp)
{
int ret;
if (sdp->metafs_fd <= 0)
return;
fsync(sdp->metafs_fd);
close(sdp->metafs_fd);
if (!sdp->metafs_mounted) { /* was mounted by us */
ret = umount(sdp->metafs_path);
if (ret)
fprintf(stderr, "Couldn't unmount %s : %s\n",
sdp->metafs_path, strerror(errno));
}
}
char *__get_sysfs(char *fsname, char *filename)
{
char path[PATH_MAX];
int fd, rv;
memset(path, 0, PATH_MAX);
memset(sysfs_buf, 0, PAGE_SIZE);
snprintf(path, PATH_MAX - 1, "%s/%s/%s", SYS_BASE, fsname, filename);
fd = open(path, O_RDONLY);
if (fd < 0)
die("can't open %s: %s\n", path, strerror(errno));
rv = read(fd, sysfs_buf, PAGE_SIZE);
if (rv < 0)
die("can't read from %s: %s\n", path, strerror(errno));
close(fd);
return sysfs_buf;
}
char *
get_sysfs(char *fsname, char *filename)
{
char *p = strchr(__get_sysfs(fsname, filename), '\n');
if (p)
*p = '\0';
return sysfs_buf;
}
unsigned int
get_sysfs_uint(char *fsname, char *filename)
{
unsigned int x;
sscanf(__get_sysfs(fsname, filename), "%u", &x);
return x;
}
void
set_sysfs(char *fsname, char *filename, char *val)
{
char path[PATH_MAX];
int fd, rv, len;
len = strlen(val) + 1;
if (len > PAGE_SIZE)
die("value for %s is too larger for sysfs\n", path);
memset(path, 0, PATH_MAX);
snprintf(path, PATH_MAX - 1, "%s/%s/%s", SYS_BASE, fsname, filename);
fd = open(path, O_WRONLY);
if (fd < 0)
die("can't open %s: %s\n", path, strerror(errno));
rv = write(fd, val, len);
if (rv != len){
if (rv < 0)
die("can't write to %s: %s", path, strerror(errno));
else
die("tried to write %d bytes to path, wrote %d\n",
len, rv);
}
close(fd);
}
/**
* get_list - Get the list of GFS2 filesystems
*
* Returns: a NULL terminated string
*/
#define LIST_SIZE 1048576
char *
get_list(void)
{
char path[PATH_MAX];
char s_id[PATH_MAX];
char *list, *p;
int rv, fd, x = 0, total = 0;
DIR *d;
struct dirent *de;
list = malloc(LIST_SIZE);
if (!list)
die("out of memory\n");
memset(path, 0, PATH_MAX);
snprintf(path, PATH_MAX, "%s", SYS_BASE);
d = opendir(path);
if (!d)
die("can't open %s: %s\n", SYS_BASE, strerror(errno));
while ((de = readdir(d))) {
if (de->d_name[0] == '.')
continue;
memset(path, 0, PATH_MAX);
snprintf(path, PATH_MAX, "%s/%s/id", SYS_BASE, de->d_name);
fd = open(path, O_RDONLY);
if (fd < 0)
die("can't open %s: %s\n", path, strerror(errno));
memset(s_id, 0, PATH_MAX);
rv = read(fd, s_id, sizeof(s_id));
if (rv < 0)
die("can't read %s: %s\n", path, strerror(errno));
close(fd);
p = strstr(s_id, "\n");
if (p)
*p = '\0';
total += strlen(s_id) + strlen(de->d_name) + 2;
if (total > LIST_SIZE)
break;
x += sprintf(list + x, "%s %s\n", s_id, de->d_name);
}
closedir(d);
return list;
}
/**
* str2lines - parse a string into lines
* @list: the list
*
* Returns: An array of character pointers
*/
char **
str2lines(char *str)
{
char *p;
unsigned int n = 0;
char **lines;
unsigned int x = 0;
for (p = str; *p; p++)
if (*p == '\n')
n++;
lines = malloc((n + 1) * sizeof(char *));
if (!lines)
die("out of memory\n");
for (lines[x] = p = str; *p; p++)
if (*p == '\n') {
*p = 0;
lines[++x] = p + 1;
}
return lines;
}
/**
* do_basename - Create dm-N style name for the device
* @device:
*
* Returns: Pointer to dm name or basename
*/
char *
do_basename(char *device)
{
FILE *file;
int found = FALSE;
char line[PATH_MAX], major_name[PATH_MAX];
unsigned int major_number;
struct stat st;
file = fopen("/proc/devices", "r");
if (!file)
goto punt;
while (fgets(line, PATH_MAX, file)) {
if (sscanf(line, "%u %s", &major_number, major_name) != 2)
continue;
if (strcmp(major_name, "device-mapper") != 0)
continue;
found = TRUE;
break;
}
fclose(file);
if (!found)
goto punt;
if (stat(device, &st))
goto punt;
if (major(st.st_rdev) == major_number) {
static char realname[16];
snprintf(realname, 16, "dm-%u", minor(st.st_rdev));
return realname;
}
punt:
return basename(device);
}
char *
mp2devname(char *mp)
{
FILE *file;
char line[PATH_MAX];
static char device[PATH_MAX];
char *name = NULL;
char *realname;
realname = realpath(mp, NULL);
if (!realname)
die("Unable to allocate memory for name resolution.\n");
file = fopen("/proc/mounts", "r");
if (!file)
die("can't open /proc/mounts: %s\n", strerror(errno));
while (fgets(line, PATH_MAX, file)) {
char path[PATH_MAX], type[PATH_MAX];
if (sscanf(line, "%s %s %s", device, path, type) != 3)
continue;
if (strcmp(path, realname))
continue;
if (strcmp(type, "gfs2"))
die("%s is not a GFS2 filesystem\n", mp);
name = do_basename(device);
break;
}
free(realname);
fclose(file);
return name;
}
char *
find_debugfs_mount(void)
{
FILE *file;
char line[PATH_MAX];
char device[PATH_MAX], type[PATH_MAX];
char *path;
file = fopen("/proc/mounts", "rt");
if (!file)
die("can't open /proc/mounts: %s\n", strerror(errno));
path = malloc(PATH_MAX);
if (!path)
die("Can't allocate memory for debugfs.\n");
while (fgets(line, PATH_MAX, file)) {
if (sscanf(line, "%s %s %s", device, path, type) != 3)
continue;
if (!strcmp(type, "debugfs")) {
fclose(file);
return path;
}
}
free(path);
fclose(file);
return NULL;
}
/* The fsname can be substituted for the mountpoint on the command line.
This is necessary when we can't resolve a devname from /proc/mounts
to a fsname. */
int is_fsname(char *name)
{
int rv = 0;
DIR *d;
struct dirent *de;
d = opendir(SYS_BASE);
if (!d)
die("can't open %s: %s\n", SYS_BASE, strerror(errno));
while ((de = readdir(d))) {
if (de->d_name[0] == '.')
continue;
if (strcmp(de->d_name, name) == 0) {
rv = 1;
break;
}
}
closedir(d);
return rv;
}
/**
* mp2fsname - Find the name for a filesystem given its mountpoint
*
* We do this by iterating through gfs2 dirs in /sys/fs/gfs2/ looking for
* one where the "id" attribute matches the device id returned by stat for
* the mount point. The reason we go through all this is simple: the
* kernel's sysfs is named after the VFS s_id, not the device name.
* So it's perfectly legal to do something like this to simulate user
* conditions without the proper hardware:
* # rm /dev/sdb1
* # mkdir /dev/cciss
* # mknod /dev/cciss/c0d0p1 b 8 17
* # mount -tgfs2 /dev/cciss/c0d0p1 /mnt/gfs2
* # gfs2_tool gettune /mnt/gfs2
* In this example the tuning variables are in a directory named after the
* VFS s_id, which in this case would be /sys/fs/gfs2/sdb1/
*
* Returns: the fsname
*/
char *
mp2fsname(char *mp)
{
char device_id[PATH_MAX], *fsname = NULL;
struct stat statbuf;
DIR *d;
struct dirent *de;
if (stat(mp, &statbuf))
return NULL;
memset(device_id, 0, sizeof(device_id));
sprintf(device_id, "%i:%i", major(statbuf.st_dev),
minor(statbuf.st_dev));
d = opendir(SYS_BASE);
if (!d)
die("can't open %s: %s\n", SYS_BASE, strerror(errno));
while ((de = readdir(d))) {
if (de->d_name[0] == '.')
continue;
if (strcmp(get_sysfs(de->d_name, "id"), device_id) == 0) {
fsname = strdup(de->d_name);
break;
}
}
closedir(d);
return fsname;
}
/**
* name2value - find the value of a name-value pair in a string
* @str_in:
* @name:
*
* Returns: the value string in a static buffer
*/
char *
name2value(char *str_in, char *name)
{
char str[strlen(str_in) + 1];
static char value[PATH_MAX];
char **lines;
unsigned int x;
unsigned int len = strlen(name);
strcpy(str, str_in);
value[0] = 0;
lines = str2lines(str);
for (x = 0; *lines[x]; x++)
if (memcmp(lines[x], name, len) == 0 &&
lines[x][len] == ' ') {
strcpy(value, lines[x] + len + 1);
break;
}
free(lines);
return value;
}
/**
* name2u32 - find the value of a name-value pair in a string
* @str_in:
* @name:
*
* Returns: the value uint32
*/
uint32_t
name2u32(char *str, char *name)
{
char *value = name2value(str, name);
uint32_t x = 0;
sscanf(value, "%u", &x);
return x;
}
/**
* name2u64 - find the value of a name-value pair in a string
* @str_in:
* @name:
*
* Returns: the value uint64
*/
uint64_t
name2u64(char *str, char *name)
{
char *value = name2value(str, name);
uint64_t x = 0;
sscanf(value, "%"SCNu64, &x);
return x;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Nov 23, 11:08 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1018654
Default Alt Text
(15 KB)
Attached To
Mode
rR Resource Agents
Attached
Detach File
Event Timeline
Log In to Comment