Merge branches 'hammer2' and 'master' of ssh://crater.dragonflybsd.org/repository...
[dragonfly.git] / sys / vfs / hammer2 / hammer2_ioctl.c
1 /*
2  * Copyright (c) 2011-2012 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@dragonflybsd.org>
6  * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org>
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  * 3. Neither the name of The DragonFly Project nor the names of its
19  *    contributors may be used to endorse or promote products derived
20  *    from this software without specific, prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
26  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
30  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 /*
36  * Ioctl Functions.
37  *
38  * WARNING! The ioctl functions which manipulate the connection state need
39  *          to be able to run without deadlock on the volume's chain lock.
40  *          Most of these functions use a separate lock.
41  */
42
43 #include "hammer2.h"
44
45 static int hammer2_ioctl_get_version(hammer2_inode_t *ip, void *data);
46 static int hammer2_ioctl_get_remote(hammer2_inode_t *ip, void *data);
47 static int hammer2_ioctl_add_remote(hammer2_inode_t *ip, void *data);
48 static int hammer2_ioctl_del_remote(hammer2_inode_t *ip, void *data);
49 static int hammer2_ioctl_rep_remote(hammer2_inode_t *ip, void *data);
50 static int hammer2_ioctl_get_socket(hammer2_inode_t *ip, void *data);
51 static int hammer2_ioctl_set_socket(hammer2_inode_t *ip, void *data);
52
53 int
54 hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, int fflag,
55               struct ucred *cred)
56 {
57         int error;
58
59         /*
60          * Standard root cred checks, will be selectively ignored below
61          * for ioctls that do not require root creds.
62          */
63         error = priv_check_cred(cred, PRIV_HAMMER_IOCTL, 0);
64
65         switch(com) {
66         case HAMMER2IOC_GET_VERSION:
67                 /*
68                  * Retrieve version and basic status
69                  */
70                 error = hammer2_ioctl_get_version(ip, data);
71                 break;
72         case HAMMER2IOC_GET_REMOTE:
73                 /*
74                  * Retrieve information about a remote
75                  */
76                 if (error == 0)
77                         error = hammer2_ioctl_get_remote(ip, data);
78                 break;
79         case HAMMER2IOC_ADD_REMOTE:
80                 /*
81                  * Add new remote entry.
82                  */
83                 if (error == 0)
84                         error = hammer2_ioctl_add_remote(ip, data);
85                 break;
86         case HAMMER2IOC_DEL_REMOTE:
87                 /*
88                  * Delete existing remote entry
89                  */
90                 if (error == 0)
91                         error = hammer2_ioctl_del_remote(ip, data);
92                 break;
93         case HAMMER2IOC_REP_REMOTE:
94                 /*
95                  * Replace existing remote entry
96                  */
97                 if (error == 0)
98                         error = hammer2_ioctl_rep_remote(ip, data);
99                 break;
100         case HAMMER2IOC_GET_SOCKET:
101                 /*
102                  * Retrieve communications socket
103                  */
104                 if (error == 0)
105                         error = hammer2_ioctl_get_socket(ip, data);
106                 break;
107         case HAMMER2IOC_SET_SOCKET:
108                 /*
109                  * Set communications socket for connection
110                  */
111                 if (error == 0)
112                         error = hammer2_ioctl_set_socket(ip, data);
113                 break;
114         default:
115                 error = EOPNOTSUPP;
116                 break;
117         }
118         return (error);
119 }
120
121 /*
122  * Retrieve version and basic info
123  */
124 static int
125 hammer2_ioctl_get_version(hammer2_inode_t *ip, void *data)
126 {
127         hammer2_mount_t *hmp = ip->hmp;
128         hammer2_ioc_version_t *version = data;
129
130         version->version = hmp->voldata.version;
131         return 0;
132 }
133
134 /*
135  * Retrieve information about a remote
136  */
137 static int
138 hammer2_ioctl_get_remote(hammer2_inode_t *ip, void *data)
139 {
140         hammer2_mount_t *hmp = ip->hmp;
141         hammer2_ioc_remote_t *remote = data;
142         int copyid = remote->copyid;
143
144         if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
145                 return (EINVAL);
146
147         hammer2_voldata_lock(hmp);
148         remote->copy1 = hmp->voldata.copyinfo[copyid];
149         hammer2_voldata_unlock(hmp);
150
151         /*
152          * Adjust nextid (GET only)
153          */
154         while (++copyid < HAMMER2_COPYID_COUNT &&
155                hmp->voldata.copyinfo[copyid].copyid == 0) {
156                 ++copyid;
157         }
158         if (copyid == HAMMER2_COPYID_COUNT)
159                 remote->nextid = -1;
160         else
161                 remote->nextid = copyid;
162
163         return(0);
164 }
165
166 /*
167  * Add new remote entry
168  */
169 static int
170 hammer2_ioctl_add_remote(hammer2_inode_t *ip, void *data)
171 {
172         hammer2_mount_t *hmp = ip->hmp;
173         hammer2_ioc_remote_t *remote = data;
174         int copyid = remote->copyid;
175         int error = 0;
176
177         if (copyid >= HAMMER2_COPYID_COUNT)
178                 return (EINVAL);
179
180         hammer2_voldata_lock(hmp);
181         if (copyid < 0) {
182                 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) {
183                         if (hmp->voldata.copyinfo[copyid].copyid == 0)
184                                 break;
185                 }
186                 if (copyid == HAMMER2_COPYID_COUNT) {
187                         error = ENOSPC;
188                         goto failed;
189                 }
190         }
191         hammer2_modify_volume(hmp);
192         kprintf("copyid %d\n", copyid);
193         remote->copy1.copyid = copyid;
194         hmp->voldata.copyinfo[copyid] = remote->copy1;
195 failed:
196         hammer2_voldata_unlock(hmp);
197         return (error);
198 }
199
200 /*
201  * Delete existing remote entry
202  */
203 static int
204 hammer2_ioctl_del_remote(hammer2_inode_t *ip, void *data)
205 {
206         hammer2_mount_t *hmp = ip->hmp;
207         hammer2_ioc_remote_t *remote = data;
208         int copyid = remote->copyid;
209         int error = 0;
210
211         if (copyid >= HAMMER2_COPYID_COUNT)
212                 return (EINVAL);
213         remote->copy1.path[sizeof(remote->copy1.path) - 1] = 0;
214         hammer2_voldata_lock(hmp);
215         if (copyid < 0) {
216                 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) {
217                         if (hmp->voldata.copyinfo[copyid].copyid == 0)
218                                 continue;
219                         if (strcmp(remote->copy1.path,
220                             hmp->voldata.copyinfo[copyid].path) == 0) {
221                                 break;
222                         }
223                 }
224                 if (copyid == HAMMER2_COPYID_COUNT) {
225                         error = ENOENT;
226                         goto failed;
227                 }
228         }
229         hammer2_modify_volume(hmp);
230         hmp->voldata.copyinfo[copyid].copyid = 0;
231 failed:
232         hammer2_voldata_unlock(hmp);
233         return (error);
234 }
235
236 /*
237  * Replace existing remote entry
238  */
239 static int
240 hammer2_ioctl_rep_remote(hammer2_inode_t *ip, void *data)
241 {
242         hammer2_mount_t *hmp = ip->hmp;
243         hammer2_ioc_remote_t *remote = data;
244         int copyid = remote->copyid;
245
246         if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
247                 return (EINVAL);
248
249         hammer2_voldata_lock(hmp);
250         hammer2_voldata_unlock(hmp);
251
252         return(0);
253 }
254
255 /*
256  * Retrieve communications socket
257  */
258 static int
259 hammer2_ioctl_get_socket(hammer2_inode_t *ip, void *data)
260 {
261         return (EOPNOTSUPP);
262 }
263
264 /*
265  * Set communications socket for connection
266  */
267 static int
268 hammer2_ioctl_set_socket(hammer2_inode_t *ip, void *data)
269 {
270         hammer2_mount_t *hmp = ip->hmp;
271         hammer2_ioc_remote_t *remote = data;
272         int copyid = remote->copyid;
273
274         if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
275                 return (EINVAL);
276
277         hammer2_voldata_lock(hmp);
278         hammer2_voldata_unlock(hmp);
279
280         return(0);
281 }