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 int lgfs2_compute_heightsize(unsigned bsize, uint64_t *heightsize,
17 uint32_t *maxheight, uint32_t bsize1, int diptrs, int inptrs)
18 {
19 heightsize[0] = bsize - sizeof(struct gfs2_dinode);
20 heightsize[1] = (uint64_t)bsize1 * diptrs;
21 for (*maxheight = 2;; (*maxheight)++) {
22 uint64_t space, d;
23 uint32_t m;
24
25 space = heightsize[*maxheight - 1] * inptrs;
26 m = space % inptrs;
27 d = space / inptrs;
28
29 if (d != heightsize[*maxheight - 1] || m)
30 break;
31 heightsize[*maxheight] = space;
32 }
33 if (*maxheight > GFS2_MAX_META_HEIGHT) {
34 errno = EINVAL;
35 return -1;
36 }
37 return 0;
38 }
39
40 int lgfs2_compute_constants(struct lgfs2_sbd *sdp)
41 {
42 sdp->md.next_inum = 1;
43 sdp->sd_time = time(NULL);
44
45 sdp->sd_bsize_shift = ffs(sdp->sd_bsize) - 1;
46 sdp->sd_fsb2bb_shift = sdp->sd_bsize_shift -
47 GFS2_BASIC_BLOCK_SHIFT;
48 sdp->sd_fsb2bb = 1 << sdp->sd_fsb2bb_shift;
49 sdp->sd_diptrs = (sdp->sd_bsize - sizeof(struct gfs2_dinode)) /
50 sizeof(uint64_t);
51 sdp->sd_inptrs = (sdp->sd_bsize - sizeof(struct gfs2_meta_header)) /
52 sizeof(uint64_t);
53 sdp->sd_jbsize = sdp->sd_bsize - sizeof(struct gfs2_meta_header);
54 sdp->sd_hash_bsize = sdp->sd_bsize / 2;
55 sdp->sd_hash_bsize_shift = sdp->sd_bsize_shift - 1;
56 sdp->sd_hash_ptrs = sdp->sd_hash_bsize / sizeof(uint64_t);
57 sdp->sd_blocks_per_bitmap = (sdp->sd_bsize - sizeof(struct gfs2_meta_header))
58 * GFS2_NBBY;
59
60 if (lgfs2_compute_heightsize(sdp->sd_bsize, sdp->sd_heightsize, &sdp->sd_max_height,
61 sdp->sd_bsize, sdp->sd_diptrs, sdp->sd_inptrs)) {
62 return -1;
63 }
64 if (lgfs2_compute_heightsize(sdp->sd_bsize, sdp->sd_jheightsize, &sdp->sd_max_jheight,
65 sdp->sd_jbsize, sdp->sd_diptrs, sdp->sd_inptrs)) {
66 return -1;
67 }
68 return 0;
69 }
70
71 /* Returns 0 if fd1 and fd2 refer to the same device/file, 1 otherwise, or -1 on error */
72 static int fdcmp(int fd1, int fd2)
73 {
74 struct stat st1, st2;
75
76 if (fd1 < 0 || fd2 < 0)
77 return -1;
78 if ((fstat(fd1, &st1) != 0) || (fstat(fd2, &st2) != 0))
79 return -1;
80 if (S_ISBLK(st1.st_mode) && S_ISBLK(st2.st_mode)) {
81 if (st1.st_rdev == st2.st_rdev) {
82 return 0;
83 }
84 } else if ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino)) {
85 return 0;
86 }
87 return 1;
88 }
89
90 int lgfs2_open_mnt(const char *path, int dirflags, int *dirfd, int devflags, int *devfd, struct mntent **mnt)
91 {
92 FILE *fp = setmntent("/proc/mounts", "r");
|
(1) Event cond_false: |
Condition "fp == NULL", taking false branch. |
93 if (fp == NULL) {
94 perror("open: /proc/mounts");
95 return 1;
|
(2) Event if_end: |
End of if statement. |
96 }
97 /* Assume path is mount point until we know better. */
|
(3) Event open_fn: |
Returning handle opened by "open". [Note: The source code implementation of the function has been overridden by a user model.] |
|
(4) Event assign: |
Assigning: "*dirfd" = "open(path, dirflags)". |
98 *dirfd = open(path, dirflags);
|
(5) Event cond_false: |
Condition "*dirfd < 0", taking false branch. |
99 if (*dirfd < 0)
|
(6) Event if_end: |
End of if statement. |
100 return 1;
101
|
(7) Event cond_true: |
Condition "(*mnt = getmntent(fp)) != NULL", taking true branch. |
102 while ((*mnt = getmntent(fp)) != NULL) {
103 int fd;
|
(8) Event cond_false: |
Condition "strcmp((*mnt)->mnt_type, "gfs2") != 0", taking false branch. |
104 if (strcmp((*mnt)->mnt_type, "gfs2") != 0)
|
(9) Event if_end: |
End of if statement. |
105 continue;
106 *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
|
(10) Event cond_true: |
Condition "strcmp(path, (*mnt)->mnt_dir) == 0", taking true branch. |
110 if (strcmp(path, (*mnt)->mnt_dir) == 0)
|
(11) Event break: |
Breaking from loop. |
111 break;
112 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 close(*dirfd);
116 *dirfd = open((*mnt)->mnt_dir, dirflags);
117 break;
118 }
119
120 fd = open((*mnt)->mnt_dir, dirflags);
121 if (fd >= 0) {
122 int diff = fdcmp(*dirfd, fd);
123 close(fd);
124 if (diff == 0)
125 break;
126 }
127 if (*devfd >= 0)
128 close(*devfd);
|
(12) Event loop_end: |
Reached end of loop. |
129 }
130 endmntent(fp);
|
(13) Event cond_false: |
Condition "*mnt == NULL", taking false branch. |
131 if (*mnt == NULL) {
132 close(*dirfd);
133 return 0; /* Success. Answer is no. Both fds closed. */
|
(14) Event if_end: |
End of if statement. |
134 }
|
(15) Event cond_false: |
Condition "*dirfd < 0", taking false branch. |
135 if (*dirfd < 0) {
136 close(*devfd);
137 return 1;
|
(16) Event if_end: |
End of if statement. |
138 }
|
(17) Event cond_false: |
Condition "*devfd < 0", taking false branch. |
139 if (*devfd < 0) {
140 close(*dirfd);
141 return 1;
|
(18) Event if_end: |
End of if statement. |
142 }
143 return 0; /* Success. Answer is yes. Both fds open. */
144 }
145
146 int lgfs2_open_mnt_dev(const char *path, int flags, struct mntent **mnt)
147 {
148 int dirfd = -1;
149 int devfd = -1;
|
(1) Event open_arg: |
"lgfs2_open_mnt" opens handle stored into "dirfd". [details] |
|
(2) Event cond_false: |
Condition "lgfs2_open_mnt(path, 0, &dirfd, flags, &devfd, mnt) != 0", taking false branch. |
| Also see events: |
[leaked_handle] |
150 if (lgfs2_open_mnt(path, O_RDONLY, &dirfd, flags, &devfd, mnt) != 0)
|
(3) Event if_end: |
End of if statement. |
151 return -1;
|
(4) Event cond_false: |
Condition "*mnt != NULL", taking false branch. |
152 if (*mnt != NULL)
|
(5) Event if_end: |
End of if statement. |
153 close(dirfd);
|
(6) Event leaked_handle: |
Handle variable "dirfd" going out of scope leaks the handle. |
| Also see events: |
[open_arg] |
154 return devfd;
155 }
156
157 int lgfs2_open_mnt_dir(const char *path, int flags, struct mntent **mnt)
158 {
159 int dirfd = -1;
160 int devfd = -1;
161 if (lgfs2_open_mnt(path, flags, &dirfd, O_RDONLY, &devfd, mnt) != 0)
162 return -1;
163 if (*mnt != NULL)
164 close(devfd);
165 return dirfd;
166 }
167