]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libnandfs/nandfs.c
Merge branch 'releng/12.2' into releng-CDN/12.2
[FreeBSD/FreeBSD.git] / lib / libnandfs / nandfs.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2010-2012 Semihalf.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <assert.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <string.h>
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <sys/ioctl.h>
41 #include <sys/stat.h>
42 #include <sys/param.h>
43 #include <sys/stdint.h>
44 #include <sys/ucred.h>
45 #include <sys/disk.h>
46 #include <sys/mount.h>
47
48 #include <fs/nandfs/nandfs_fs.h>
49 #include <libnandfs.h>
50
51 #define NANDFS_IS_VALID         0x1
52 #define NANDFS_IS_OPENED        0x2
53 #define NANDFS_IS_OPENED_DEV    0x4
54 #define NANDFS_IS_ERROR         0x8
55
56 #define DEBUG
57 #undef DEBUG
58 #ifdef DEBUG
59 #define NANDFS_DEBUG(fmt, args...) do { \
60     printf("libnandfs:" fmt "\n", ##args); } while (0)
61 #else
62 #define NANDFS_DEBUG(fmt, args...)
63 #endif
64
65 #define NANDFS_ASSERT_VALID(fs)         assert((fs)->n_flags & NANDFS_IS_VALID)
66 #define NANDFS_ASSERT_VALID_DEV(fs)     \
67         assert(((fs)->n_flags & (NANDFS_IS_VALID | NANDFS_IS_OPENED_DEV)) == \
68             (NANDFS_IS_VALID | NANDFS_IS_OPENED_DEV))
69
70 int
71 nandfs_iserror(struct nandfs *fs)
72 {
73
74         NANDFS_ASSERT_VALID(fs);
75
76         return (fs->n_flags & NANDFS_IS_ERROR);
77 }
78
79 const char *
80 nandfs_errmsg(struct nandfs *fs)
81 {
82
83         NANDFS_ASSERT_VALID(fs);
84
85         assert(nandfs_iserror(fs));
86         assert(fs->n_errmsg);
87         return (fs->n_errmsg);
88 }
89
90 static void
91 nandfs_seterr(struct nandfs *fs, const char *fmt, ...)
92 {
93         va_list ap;
94
95         va_start(ap, fmt);
96         vsnprintf(fs->n_errmsg, sizeof(fs->n_errmsg), fmt, ap);
97         va_end(ap);
98         fs->n_flags |= NANDFS_IS_ERROR;
99 }
100
101 const char *
102 nandfs_dev(struct nandfs *fs)
103 {
104
105         NANDFS_ASSERT_VALID(fs);
106         return (fs->n_dev);
107 }
108
109 void
110 nandfs_init(struct nandfs *fs, const char *dir)
111 {
112
113         snprintf(fs->n_ioc, sizeof(fs->n_ioc), "%s/%s", dir, ".");
114         fs->n_iocfd = -1;
115         fs->n_flags = NANDFS_IS_VALID;
116 }
117
118 void
119 nandfs_destroy(struct nandfs *fs)
120 {
121
122         assert(fs->n_iocfd == -1);
123         fs->n_flags &=
124             ~(NANDFS_IS_ERROR | NANDFS_IS_VALID);
125         assert(fs->n_flags == 0);
126 }
127
128 int
129 nandfs_open(struct nandfs *fs)
130 {
131         struct nandfs_fsinfo fsinfo;
132
133         fs->n_flags |= NANDFS_IS_OPENED;
134
135         fs->n_iocfd = open(fs->n_ioc, O_RDONLY, S_IRUSR | S_IWUSR | S_IRGRP |
136             S_IWGRP | S_IROTH | S_IWOTH);
137         if (fs->n_iocfd == -1) {
138                 nandfs_seterr(fs, "couldn't open %s: %s", fs->n_ioc,
139                     strerror(errno));
140                 return (-1);
141         }
142
143         if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_FSINFO, &fsinfo) == -1) {
144                 nandfs_seterr(fs, "couldn't fetch fsinfo: %s",
145                     strerror(errno));
146                 return (-1);
147         }
148
149         memcpy(&fs->n_fsdata, &fsinfo.fs_fsdata, sizeof(fs->n_fsdata));
150         memcpy(&fs->n_sb, &fsinfo.fs_super, sizeof(fs->n_sb));
151         snprintf(fs->n_dev, sizeof(fs->n_dev), "%s", fsinfo.fs_dev);
152
153         return (0);
154 }
155
156 void
157 nandfs_close(struct nandfs *fs)
158 {
159
160         NANDFS_ASSERT_VALID(fs);
161         assert(fs->n_flags & NANDFS_IS_OPENED);
162
163         close(fs->n_iocfd);
164         fs->n_iocfd = -1;
165         fs->n_flags &= ~NANDFS_IS_OPENED;
166 }
167
168 int
169 nandfs_get_cpstat(struct nandfs *fs, struct nandfs_cpstat *cpstat)
170 {
171
172         NANDFS_ASSERT_VALID(fs);
173
174         if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_CPSTAT, cpstat) == -1) {
175                 nandfs_seterr(fs, "ioctl NANDFS_IOCTL_GET_CPSTAT: %s",
176                     strerror(errno));
177                 return (-1);
178         }
179
180         return (0);
181 }
182
183 static ssize_t
184 nandfs_get_cpinfo(struct nandfs *fs, uint64_t cno, int mode,
185     struct nandfs_cpinfo *cpinfo, size_t nci)
186 {
187         struct nandfs_argv args;
188
189         NANDFS_ASSERT_VALID(fs);
190
191         args.nv_base = (u_long)cpinfo;
192         args.nv_nmembs = nci;
193         args.nv_index = cno;
194         args.nv_flags = mode;
195
196         if (ioctl(fs->n_iocfd, NANDFS_IOCTL_GET_CPINFO, &args) == -1) {
197                 nandfs_seterr(fs, "ioctl NANDFS_IOCTL_GET_CPINFO: %s",
198                     strerror(errno));
199                 return (-1);
200         }
201
202         return (args.nv_nmembs);
203 }
204
205 ssize_t
206 nandfs_get_cp(struct nandfs *fs, uint64_t cno, struct nandfs_cpinfo *cpinfo,
207     size_t nci)
208 {
209
210         return (nandfs_get_cpinfo(fs, cno, NANDFS_CHECKPOINT, cpinfo, nci));
211 }
212
213 ssize_t
214 nandfs_get_snap(struct nandfs *fs, uint64_t cno, struct nandfs_cpinfo *cpinfo,
215     size_t nci)
216 {
217
218         return (nandfs_get_cpinfo(fs, cno, NANDFS_SNAPSHOT, cpinfo, nci));
219 }
220
221 int
222 nandfs_make_snap(struct nandfs *fs, uint64_t *cno)
223 {
224
225         NANDFS_ASSERT_VALID(fs);
226
227         if (ioctl(fs->n_iocfd, NANDFS_IOCTL_MAKE_SNAP, cno) == -1) {
228                 nandfs_seterr(fs, "ioctl NANDFS_IOCTL_MAKE_SNAP: %s",
229                     strerror(errno));
230                 return (-1);
231         }
232
233         return (0);
234 }
235
236 int
237 nandfs_delete_snap(struct nandfs *fs, uint64_t cno)
238 {
239
240         NANDFS_ASSERT_VALID(fs);
241
242         if (ioctl(fs->n_iocfd, NANDFS_IOCTL_DELETE_SNAP, &cno) == -1) {
243                 nandfs_seterr(fs, "ioctl NANDFS_IOCTL_DELETE_SNAP: %s",
244                     strerror(errno));
245                 return (-1);
246         }
247
248         return (0);
249 }