Line data Source code
1 : #include "clusterautoconfig.h"
2 :
3 : #include <string.h>
4 : #include <inttypes.h>
5 : #include <sys/types.h>
6 : #include <sys/stat.h>
7 : #include <fcntl.h>
8 : #include <unistd.h>
9 : #include <time.h>
10 :
11 : #include "libgfs2.h"
12 :
13 : #define PAGE_SIZE (4096)
14 : #define DIV_RU(x, y) (((x) + (y) - 1) / (y))
15 :
16 9236 : int lgfs2_compute_heightsize(unsigned bsize, uint64_t *heightsize,
17 : uint32_t *maxheight, uint32_t bsize1, int diptrs, int inptrs)
18 : {
19 9236 : heightsize[0] = bsize - sizeof(struct gfs2_dinode);
20 9236 : heightsize[1] = (uint64_t)bsize1 * diptrs;
21 9236 : for (*maxheight = 2;; (*maxheight)++) {
22 : uint64_t space, d;
23 : uint32_t m;
24 :
25 46398 : space = heightsize[*maxheight - 1] * inptrs;
26 46398 : m = space % inptrs;
27 46398 : d = space / inptrs;
28 :
29 46398 : if (d != heightsize[*maxheight - 1] || m)
30 : break;
31 37162 : heightsize[*maxheight] = space;
32 : }
33 9236 : if (*maxheight > GFS2_MAX_META_HEIGHT) {
34 0 : errno = EINVAL;
35 0 : return -1;
36 : }
37 9236 : return 0;
38 : }
39 :
40 4618 : int lgfs2_compute_constants(struct lgfs2_sbd *sdp)
41 : {
42 4618 : sdp->md.next_inum = 1;
43 4618 : sdp->sd_time = time(NULL);
44 :
45 4618 : sdp->sd_bsize_shift = ffs(sdp->sd_bsize) - 1;
46 4618 : sdp->sd_fsb2bb_shift = sdp->sd_bsize_shift -
47 : GFS2_BASIC_BLOCK_SHIFT;
48 4618 : sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
49 4618 : sdp->sd_diptrs = (sdp->sd_bsize - sizeof(struct gfs2_dinode)) /
50 : sizeof(uint64_t);
51 4618 : sdp->sd_inptrs = (sdp->sd_bsize - sizeof(struct gfs2_meta_header)) /
52 : sizeof(uint64_t);
53 4618 : sdp->sd_jbsize = sdp->sd_bsize - sizeof(struct gfs2_meta_header);
54 4618 : sdp->sd_hash_bsize = sdp->sd_bsize / 2;
55 4618 : sdp->sd_hash_bsize_shift = sdp->sd_bsize_shift - 1;
56 4618 : sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
57 4618 : sdp->sd_blocks_per_bitmap = (sdp->sd_bsize - sizeof(struct gfs2_meta_header))
58 : * GFS2_NBBY;
59 :
60 4618 : if (lgfs2_compute_heightsize(sdp->sd_bsize, sdp->sd_heightsize, &sdp->sd_max_height,
61 4618 : sdp->sd_bsize, sdp->sd_diptrs, sdp->sd_inptrs)) {
62 0 : return -1;
63 : }
64 4618 : if (lgfs2_compute_heightsize(sdp->sd_bsize, sdp->sd_jheightsize, &sdp->sd_max_jheight,
65 4618 : sdp->sd_jbsize, sdp->sd_diptrs, sdp->sd_inptrs)) {
66 0 : return -1;
67 : }
68 4618 : return 0;
69 : }
70 :
71 : /* Returns 0 if fd1 and fd2 refer to the same device/file, 1 otherwise, or -1 on error */
72 0 : static int fdcmp(int fd1, int fd2)
73 : {
74 : struct stat st1, st2;
75 :
76 0 : if (fd1 < 0 || fd2 < 0)
77 0 : return -1;
78 0 : if ((fstat(fd1, &st1) != 0) || (fstat(fd2, &st2) != 0))
79 0 : return -1;
80 0 : if (S_ISBLK(st1.st_mode) && S_ISBLK(st2.st_mode)) {
81 0 : if (st1.st_rdev == st2.st_rdev) {
82 0 : return 0;
83 : }
84 0 : } else if ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino)) {
85 0 : return 0;
86 : }
87 0 : return 1;
88 : }
89 :
90 0 : int lgfs2_open_mnt(const char *path, int dirflags, int *dirfd, int devflags, int *devfd, struct mntent **mnt)
91 : {
92 0 : FILE *fp = setmntent("/proc/mounts", "r");
93 0 : if (fp == NULL) {
94 0 : perror("open: /proc/mounts");
95 0 : return 1;
96 : }
97 : /* Assume path is mount point until we know better. */
98 0 : *dirfd = open(path, dirflags);
99 0 : if (*dirfd < 0)
100 0 : return 1;
101 :
102 0 : while ((*mnt = getmntent(fp)) != NULL) {
103 : int fd;
104 0 : if (strcmp((*mnt)->mnt_type, "gfs2") != 0)
105 0 : continue;
106 0 : *devfd = open((*mnt)->mnt_fsname, devflags);
107 : /* Defer checking *devfd until later: whether it's ok to ignore
108 : * the error depends on whether we find the mount point. */
109 :
110 0 : if (strcmp(path, (*mnt)->mnt_dir) == 0)
111 0 : break;
112 0 : if (strcmp(path, (*mnt)->mnt_fsname) == 0 || fdcmp(*dirfd, *devfd) == 0) {
113 : /* We have a match but our above assumption was
114 : incorrect and *dirfd is actually the device. */
115 0 : close(*dirfd);
116 0 : *dirfd = open((*mnt)->mnt_dir, dirflags);
117 0 : break;
118 : }
119 :
120 0 : fd = open((*mnt)->mnt_dir, dirflags);
121 0 : if (fd >= 0) {
122 0 : int diff = fdcmp(*dirfd, fd);
123 0 : close(fd);
124 0 : if (diff == 0)
125 0 : break;
126 : }
127 0 : if (*devfd >= 0)
128 0 : close(*devfd);
129 : }
130 0 : endmntent(fp);
131 0 : if (*mnt == NULL) {
132 0 : close(*dirfd);
133 0 : return 0; /* Success. Answer is no. Both fds closed. */
134 : }
135 0 : if (*dirfd < 0) {
136 0 : close(*devfd);
137 0 : return 1;
138 : }
139 0 : if (*devfd < 0) {
140 0 : close(*dirfd);
141 0 : return 1;
142 : }
143 0 : return 0; /* Success. Answer is yes. Both fds open. */
144 : }
145 :
146 0 : int lgfs2_open_mnt_dev(const char *path, int flags, struct mntent **mnt)
147 : {
148 0 : int dirfd = -1;
149 0 : int devfd = -1;
150 0 : if (lgfs2_open_mnt(path, O_RDONLY, &dirfd, flags, &devfd, mnt) != 0)
151 0 : return -1;
152 0 : if (*mnt != NULL)
153 0 : close(dirfd);
154 0 : return devfd;
155 : }
156 :
157 0 : int lgfs2_open_mnt_dir(const char *path, int flags, struct mntent **mnt)
158 : {
159 0 : int dirfd = -1;
160 0 : int devfd = -1;
161 0 : if (lgfs2_open_mnt(path, flags, &dirfd, O_RDONLY, &devfd, mnt) != 0)
162 0 : return -1;
163 0 : if (*mnt != NULL)
164 0 : close(devfd);
165 0 : return dirfd;
166 : }
|