hammer2 - multi-target mount part 4/many (stabilization)
[dragonfly.git] / sys / vfs / hammer2 / hammer2_ioctl.c
1 /*
2  * Copyright (c) 2011-2014 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_version_get(hammer2_inode_t *ip, void *data);
46 static int hammer2_ioctl_recluster(hammer2_inode_t *ip, void *data);
47 static int hammer2_ioctl_remote_scan(hammer2_inode_t *ip, void *data);
48 static int hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data);
49 static int hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data);
50 static int hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data);
51 static int hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data);
52 static int hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data);
53 static int hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data);
54 static int hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data);
55 static int hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data);
56 static int hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data);
57 static int hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data);
58 static int hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data);
59 static int hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data);
60 static int hammer2_ioctl_debug_dump(hammer2_inode_t *ip);
61 //static int hammer2_ioctl_inode_comp_set(hammer2_inode_t *ip, void *data);
62 //static int hammer2_ioctl_inode_comp_rec_set(hammer2_inode_t *ip, void *data);
63 //static int hammer2_ioctl_inode_comp_rec_set2(hammer2_inode_t *ip, void *data);
64
65 int
66 hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, int fflag,
67               struct ucred *cred)
68 {
69         int error;
70
71         /*
72          * Standard root cred checks, will be selectively ignored below
73          * for ioctls that do not require root creds.
74          */
75         error = priv_check_cred(cred, PRIV_HAMMER_IOCTL, 0);
76
77         switch(com) {
78         case HAMMER2IOC_VERSION_GET:
79                 error = hammer2_ioctl_version_get(ip, data);
80                 break;
81         case HAMMER2IOC_RECLUSTER:
82                 if (error == 0)
83                         error = hammer2_ioctl_recluster(ip, data);
84                 break;
85         case HAMMER2IOC_REMOTE_SCAN:
86                 if (error == 0)
87                         error = hammer2_ioctl_remote_scan(ip, data);
88                 break;
89         case HAMMER2IOC_REMOTE_ADD:
90                 if (error == 0)
91                         error = hammer2_ioctl_remote_add(ip, data);
92                 break;
93         case HAMMER2IOC_REMOTE_DEL:
94                 if (error == 0)
95                         error = hammer2_ioctl_remote_del(ip, data);
96                 break;
97         case HAMMER2IOC_REMOTE_REP:
98                 if (error == 0)
99                         error = hammer2_ioctl_remote_rep(ip, data);
100                 break;
101         case HAMMER2IOC_SOCKET_GET:
102                 if (error == 0)
103                         error = hammer2_ioctl_socket_get(ip, data);
104                 break;
105         case HAMMER2IOC_SOCKET_SET:
106                 if (error == 0)
107                         error = hammer2_ioctl_socket_set(ip, data);
108                 break;
109         case HAMMER2IOC_PFS_GET:
110                 if (error == 0)
111                         error = hammer2_ioctl_pfs_get(ip, data);
112                 break;
113         case HAMMER2IOC_PFS_LOOKUP:
114                 if (error == 0)
115                         error = hammer2_ioctl_pfs_lookup(ip, data);
116                 break;
117         case HAMMER2IOC_PFS_CREATE:
118                 if (error == 0)
119                         error = hammer2_ioctl_pfs_create(ip, data);
120                 break;
121         case HAMMER2IOC_PFS_DELETE:
122                 if (error == 0)
123                         error = hammer2_ioctl_pfs_delete(ip, data);
124                 break;
125         case HAMMER2IOC_PFS_SNAPSHOT:
126                 if (error == 0)
127                         error = hammer2_ioctl_pfs_snapshot(ip, data);
128                 break;
129         case HAMMER2IOC_INODE_GET:
130                 error = hammer2_ioctl_inode_get(ip, data);
131                 break;
132         case HAMMER2IOC_INODE_SET:
133                 if (error == 0)
134                         error = hammer2_ioctl_inode_set(ip, data);
135                 break;
136         /*case HAMMER2IOC_INODE_COMP_SET:
137                 error = hammer2_ioctl_inode_comp_set(ip, data);
138                 break;
139         case HAMMER2IOC_INODE_COMP_REC_SET:
140                 error = hammer2_ioctl_inode_comp_rec_set(ip, data);
141                 break;
142         case HAMMER2IOC_INODE_COMP_REC_SET2:
143                 error = hammer2_ioctl_inode_comp_rec_set2(ip, data);
144                 break;*/
145         case HAMMER2IOC_DEBUG_DUMP:
146                 error = hammer2_ioctl_debug_dump(ip);
147                 break;
148         default:
149                 error = EOPNOTSUPP;
150                 break;
151         }
152         return (error);
153 }
154
155 /*
156  * Retrieve version and basic info
157  */
158 static int
159 hammer2_ioctl_version_get(hammer2_inode_t *ip, void *data)
160 {
161         hammer2_mount_t *hmp = ip->pmp->iroot->cluster.focus->hmp;
162         hammer2_ioc_version_t *version = data;
163
164         version->version = hmp->voldata.version;
165         return 0;
166 }
167
168 static int
169 hammer2_ioctl_recluster(hammer2_inode_t *ip, void *data)
170 {
171         hammer2_ioc_recluster_t *recl = data;
172         struct file *fp;
173
174         fp = holdfp(curproc->p_fd, recl->fd, -1);
175         if (fp) {
176                 kprintf("reconnect to cluster\n");
177                 hammer2_cluster_reconnect(ip->pmp, fp);
178                 return 0;
179         } else {
180                 return EINVAL;
181         }
182 }
183
184 /*
185  * Retrieve information about a remote
186  */
187 static int
188 hammer2_ioctl_remote_scan(hammer2_inode_t *ip, void *data)
189 {
190         hammer2_mount_t *hmp = ip->pmp->iroot->cluster.focus->hmp;
191         hammer2_ioc_remote_t *remote = data;
192         int copyid = remote->copyid;
193
194         if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
195                 return (EINVAL);
196
197         hammer2_voldata_lock(hmp);
198         remote->copy1 = hmp->voldata.copyinfo[copyid];
199         hammer2_voldata_unlock(hmp);
200
201         /*
202          * Adjust nextid (GET only)
203          */
204         while (++copyid < HAMMER2_COPYID_COUNT &&
205                hmp->voldata.copyinfo[copyid].copyid == 0) {
206                 ;
207         }
208         if (copyid == HAMMER2_COPYID_COUNT)
209                 remote->nextid = -1;
210         else
211                 remote->nextid = copyid;
212
213         return(0);
214 }
215
216 /*
217  * Add new remote entry
218  */
219 static int
220 hammer2_ioctl_remote_add(hammer2_inode_t *ip, void *data)
221 {
222         hammer2_ioc_remote_t *remote = data;
223         hammer2_pfsmount_t *pmp = ip->pmp;
224         hammer2_mount_t *hmp;
225         int copyid = remote->copyid;
226         int error = 0;
227
228         if (copyid >= HAMMER2_COPYID_COUNT)
229                 return (EINVAL);
230
231         hmp = pmp->iroot->cluster.focus->hmp; /* XXX */
232         hammer2_voldata_lock(hmp);
233         if (copyid < 0) {
234                 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) {
235                         if (hmp->voldata.copyinfo[copyid].copyid == 0)
236                                 break;
237                 }
238                 if (copyid == HAMMER2_COPYID_COUNT) {
239                         error = ENOSPC;
240                         goto failed;
241                 }
242         }
243         hammer2_voldata_modify(hmp);
244         remote->copy1.copyid = copyid;
245         hmp->voldata.copyinfo[copyid] = remote->copy1;
246         hammer2_volconf_update(pmp, copyid);
247 failed:
248         hammer2_voldata_unlock(hmp);
249         return (error);
250 }
251
252 /*
253  * Delete existing remote entry
254  */
255 static int
256 hammer2_ioctl_remote_del(hammer2_inode_t *ip, void *data)
257 {
258         hammer2_ioc_remote_t *remote = data;
259         hammer2_pfsmount_t *pmp = ip->pmp;
260         hammer2_mount_t *hmp;
261         int copyid = remote->copyid;
262         int error = 0;
263
264         hmp = pmp->iroot->cluster.focus->hmp; /* XXX */
265         if (copyid >= HAMMER2_COPYID_COUNT)
266                 return (EINVAL);
267         remote->copy1.path[sizeof(remote->copy1.path) - 1] = 0;
268         hammer2_voldata_lock(hmp);
269         if (copyid < 0) {
270                 for (copyid = 1; copyid < HAMMER2_COPYID_COUNT; ++copyid) {
271                         if (hmp->voldata.copyinfo[copyid].copyid == 0)
272                                 continue;
273                         if (strcmp(remote->copy1.path,
274                             hmp->voldata.copyinfo[copyid].path) == 0) {
275                                 break;
276                         }
277                 }
278                 if (copyid == HAMMER2_COPYID_COUNT) {
279                         error = ENOENT;
280                         goto failed;
281                 }
282         }
283         hammer2_voldata_modify(hmp);
284         hmp->voldata.copyinfo[copyid].copyid = 0;
285         hammer2_volconf_update(pmp, copyid);
286 failed:
287         hammer2_voldata_unlock(hmp);
288         return (error);
289 }
290
291 /*
292  * Replace existing remote entry
293  */
294 static int
295 hammer2_ioctl_remote_rep(hammer2_inode_t *ip, void *data)
296 {
297         hammer2_ioc_remote_t *remote = data;
298         hammer2_mount_t *hmp;
299         int copyid = remote->copyid;
300
301         hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
302
303         if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
304                 return (EINVAL);
305
306         hammer2_voldata_lock(hmp);
307         hammer2_voldata_modify(hmp);
308         /*hammer2_volconf_update(pmp, copyid);*/
309         hammer2_voldata_unlock(hmp);
310
311         return(0);
312 }
313
314 /*
315  * Retrieve communications socket
316  */
317 static int
318 hammer2_ioctl_socket_get(hammer2_inode_t *ip, void *data)
319 {
320         return (EOPNOTSUPP);
321 }
322
323 /*
324  * Set communications socket for connection
325  */
326 static int
327 hammer2_ioctl_socket_set(hammer2_inode_t *ip, void *data)
328 {
329         hammer2_ioc_remote_t *remote = data;
330         hammer2_mount_t *hmp;
331         int copyid = remote->copyid;
332
333         hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
334         if (copyid < 0 || copyid >= HAMMER2_COPYID_COUNT)
335                 return (EINVAL);
336
337         hammer2_voldata_lock(hmp);
338         hammer2_voldata_unlock(hmp);
339
340         return(0);
341 }
342
343 /*
344  * Used to scan and retrieve PFS information.  PFS's are directories under
345  * the super-root.
346  *
347  * To scan PFSs pass name_key=0.  The function will scan for the next
348  * PFS and set all fields, as well as set name_next to the next key.
349  * When no PFSs remain, name_next is set to (hammer2_key_t)-1.
350  *
351  * To retrieve the PFS associated with the file descriptor, pass
352  * name_key set to (hammer2_key_t)-1.
353  */
354 static int
355 hammer2_ioctl_pfs_get(hammer2_inode_t *ip, void *data)
356 {
357         const hammer2_inode_data_t *ipdata;
358         hammer2_mount_t *hmp;
359         hammer2_ioc_pfs_t *pfs;
360         hammer2_cluster_t *cparent;
361         hammer2_cluster_t *rcluster;
362         hammer2_cluster_t *cluster;
363         hammer2_key_t key_next;
364         int error;
365         int ddflag;
366
367         error = 0;
368         hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
369         pfs = data;
370         cparent = hammer2_inode_lock_ex(hmp->spmp->iroot);
371         rcluster = hammer2_inode_lock_ex(ip->pmp->iroot);
372
373         /*
374          * Search for the first key or specific key.  Remember that keys
375          * can be returned in any order.
376          */
377         if (pfs->name_key == 0) {
378                 cluster = hammer2_cluster_lookup(cparent, &key_next,
379                                                  0, (hammer2_key_t)-1,
380                                                  0, &ddflag);
381         } else if (pfs->name_key == (hammer2_key_t)-1) {
382                 ipdata = &hammer2_cluster_data(rcluster)->ipdata;
383                 cluster = hammer2_cluster_lookup(cparent, &key_next,
384                                                  ipdata->name_key,
385                                                  ipdata->name_key,
386                                                  0, &ddflag);
387                 ipdata = NULL;  /* safety */
388         } else {
389                 cluster = hammer2_cluster_lookup(cparent, &key_next,
390                                                  pfs->name_key, pfs->name_key,
391                                                  0, &ddflag);
392         }
393         hammer2_inode_unlock_ex(ip->pmp->iroot, rcluster);
394
395         while (cluster &&
396                hammer2_cluster_type(cluster) != HAMMER2_BREF_TYPE_INODE) {
397                 cluster = hammer2_cluster_next(cparent, cluster, &key_next,
398                                                key_next, (hammer2_key_t)-1,
399                                                0);
400         }
401         if (cluster) {
402                 /*
403                  * Load the data being returned by the ioctl.
404                  */
405                 ipdata = &hammer2_cluster_data(cluster)->ipdata;
406                 pfs->name_key = ipdata->name_key;
407                 pfs->pfs_type = ipdata->pfs_type;
408                 pfs->pfs_clid = ipdata->pfs_clid;
409                 pfs->pfs_fsid = ipdata->pfs_fsid;
410                 KKASSERT(ipdata->name_len < sizeof(pfs->name));
411                 bcopy(ipdata->filename, pfs->name, ipdata->name_len);
412                 pfs->name[ipdata->name_len] = 0;
413                 ipdata = NULL;  /* safety */
414
415                 /*
416                  * Calculate the next field
417                  */
418                 do {
419                         cluster = hammer2_cluster_next(cparent, cluster,
420                                                        &key_next,
421                                                        0, (hammer2_key_t)-1,
422                                                        0);
423                 } while (cluster &&
424                          hammer2_cluster_type(cluster) !=
425                           HAMMER2_BREF_TYPE_INODE);
426                 if (cluster) {
427                         ipdata = &hammer2_cluster_data(cluster)->ipdata;
428                         pfs->name_next = ipdata->name_key;
429                         hammer2_cluster_unlock(cluster);
430                 } else {
431                         pfs->name_next = (hammer2_key_t)-1;
432                 }
433         } else {
434                 pfs->name_next = (hammer2_key_t)-1;
435                 error = ENOENT;
436         }
437         hammer2_inode_unlock_ex(hmp->spmp->iroot, cparent);
438
439         return (error);
440 }
441
442 /*
443  * Find a specific PFS by name
444  */
445 static int
446 hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data)
447 {
448         const hammer2_inode_data_t *ipdata;
449         hammer2_mount_t *hmp;
450         hammer2_ioc_pfs_t *pfs;
451         hammer2_cluster_t *cparent;
452         hammer2_cluster_t *cluster;
453         hammer2_key_t key_next;
454         hammer2_key_t lhc;
455         int error;
456         int ddflag;
457         size_t len;
458
459         error = 0;
460         hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
461         pfs = data;
462         cparent = hammer2_inode_lock_sh(hmp->spmp->iroot);
463
464         pfs->name[sizeof(pfs->name) - 1] = 0;
465         len = strlen(pfs->name);
466         lhc = hammer2_dirhash(pfs->name, len);
467
468         cluster = hammer2_cluster_lookup(cparent, &key_next,
469                                          lhc, lhc + HAMMER2_DIRHASH_LOMASK,
470                                          HAMMER2_LOOKUP_SHARED, &ddflag);
471         while (cluster) {
472                 if (hammer2_cluster_type(cluster) == HAMMER2_BREF_TYPE_INODE) {
473                         ipdata = &hammer2_cluster_data(cluster)->ipdata;
474                         if (ipdata->name_len == len &&
475                             bcmp(ipdata->filename, pfs->name, len) == 0) {
476                                 break;
477                         }
478                         ipdata = NULL;  /* safety */
479                 }
480                 cluster = hammer2_cluster_next(cparent, cluster, &key_next,
481                                            key_next,
482                                            lhc + HAMMER2_DIRHASH_LOMASK,
483                                            HAMMER2_LOOKUP_SHARED);
484         }
485
486         /*
487          * Load the data being returned by the ioctl.
488          */
489         if (cluster) {
490                 ipdata = &hammer2_cluster_data(cluster)->ipdata;
491                 pfs->name_key = ipdata->name_key;
492                 pfs->pfs_type = ipdata->pfs_type;
493                 pfs->pfs_clid = ipdata->pfs_clid;
494                 pfs->pfs_fsid = ipdata->pfs_fsid;
495                 ipdata = NULL;
496
497                 hammer2_cluster_unlock(cluster);
498         } else {
499                 error = ENOENT;
500         }
501         hammer2_inode_unlock_sh(hmp->spmp->iroot, cparent);
502
503         return (error);
504 }
505
506 /*
507  * Create a new PFS under the super-root
508  */
509 static int
510 hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data)
511 {
512         hammer2_inode_data_t *nipdata;
513         hammer2_mount_t *hmp;
514         hammer2_ioc_pfs_t *pfs;
515         hammer2_inode_t *nip;
516         hammer2_cluster_t *ncluster;
517         hammer2_trans_t trans;
518         int error;
519
520         hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
521         pfs = data;
522         nip = NULL;
523
524         if (pfs->name[0] == 0)
525                 return(EINVAL);
526         pfs->name[sizeof(pfs->name) - 1] = 0;   /* ensure 0-termination */
527
528         hammer2_trans_init(&trans, ip->pmp, HAMMER2_TRANS_NEWINODE);
529         nip = hammer2_inode_create(&trans, hmp->spmp->iroot, NULL, NULL,
530                                      pfs->name, strlen(pfs->name),
531                                      &ncluster, &error);
532         if (error == 0) {
533                 nipdata = hammer2_cluster_modify_ip(&trans, nip, ncluster,
534                                                   HAMMER2_MODIFY_ASSERTNOCOPY);
535                 nipdata->pfs_type = pfs->pfs_type;
536                 nipdata->pfs_clid = pfs->pfs_clid;
537                 nipdata->pfs_fsid = pfs->pfs_fsid;
538
539                 /*
540                  * Do not allow compression on PFS's with the special name
541                  * "boot", the boot loader can't decompress (yet).
542                  */
543                 if (strcmp(pfs->name, "boot") == 0)
544                         nipdata->comp_algo = HAMMER2_COMP_AUTOZERO;
545                 hammer2_cluster_modsync(ncluster);
546                 hammer2_inode_unlock_ex(nip, ncluster);
547         }
548         hammer2_trans_done(&trans);
549
550         return (error);
551 }
552
553 /*
554  * Destroy an existing PFS under the super-root
555  */
556 static int
557 hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data)
558 {
559         hammer2_mount_t *hmp;
560         hammer2_ioc_pfs_t *pfs = data;
561         hammer2_trans_t trans;
562         int error;
563
564         hmp = ip->pmp->iroot->cluster.focus->hmp; /* XXX */
565         hammer2_trans_init(&trans, ip->pmp, 0);
566         error = hammer2_unlink_file(&trans, hmp->spmp->iroot,
567                                     pfs->name, strlen(pfs->name),
568                                     2, NULL, NULL);
569         hammer2_trans_done(&trans);
570
571         return (error);
572 }
573
574 static int
575 hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data)
576 {
577         hammer2_ioc_pfs_t *pfs = data;
578         hammer2_trans_t trans;
579         hammer2_cluster_t *cparent;
580         int error;
581
582         if (pfs->name[0] == 0)
583                 return(EINVAL);
584         if (pfs->name[sizeof(pfs->name)-1] != 0)
585                 return(EINVAL);
586
587         hammer2_vfs_sync(ip->pmp->mp, MNT_WAIT);
588
589         hammer2_trans_init(&trans, ip->pmp, HAMMER2_TRANS_NEWINODE);
590         cparent = hammer2_inode_lock_ex(ip);
591         error = hammer2_cluster_snapshot(&trans, cparent, pfs);
592         hammer2_inode_unlock_ex(ip, cparent);
593         hammer2_trans_done(&trans);
594
595         return (error);
596 }
597
598 /*
599  * Retrieve the raw inode structure
600  */
601 static int
602 hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data)
603 {
604         const hammer2_inode_data_t *ipdata;
605         hammer2_ioc_inode_t *ino;
606         hammer2_cluster_t *cparent;
607
608         ino = data;
609
610         cparent = hammer2_inode_lock_sh(ip);
611         ipdata = &hammer2_cluster_data(cparent)->ipdata;
612         ino->ip_data = *ipdata;
613         ino->kdata = ip;
614         hammer2_inode_unlock_sh(ip, cparent);
615
616         return (0);
617 }
618
619 /*
620  * Set various parameters in an inode which cannot be set through
621  * normal filesystem VNOPS.
622  */
623 static int
624 hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data)
625 {
626         const hammer2_inode_data_t *ripdata;
627         hammer2_inode_data_t *wipdata;
628         hammer2_ioc_inode_t *ino = data;
629         hammer2_cluster_t *cparent;
630         hammer2_trans_t trans;
631         int error = 0;
632         int dosync = 0;
633
634         hammer2_trans_init(&trans, ip->pmp, 0);
635         cparent = hammer2_inode_lock_ex(ip);
636         ripdata = &hammer2_cluster_data(cparent)->ipdata;
637
638         if (ino->ip_data.comp_algo != ripdata->comp_algo) {
639                 wipdata = hammer2_cluster_modify_ip(&trans, ip, cparent, 0);
640                 wipdata->comp_algo = ino->ip_data.comp_algo;
641                 ripdata = wipdata; /* safety */
642                 dosync = 1;
643         }
644         ino->kdata = ip;
645         
646         /* Ignore these flags for now...*/
647         if (ino->flags & HAMMER2IOC_INODE_FLAG_IQUOTA) {
648         }
649         if (ino->flags & HAMMER2IOC_INODE_FLAG_DQUOTA) {
650         }
651         if (ino->flags & HAMMER2IOC_INODE_FLAG_COPIES) {
652         }
653         if (dosync)
654                 hammer2_cluster_modsync(cparent);
655         hammer2_trans_done(&trans);
656         hammer2_inode_unlock_ex(ip, cparent);
657
658         return (error);
659 }
660
661 static
662 int
663 hammer2_ioctl_debug_dump(hammer2_inode_t *ip)
664 {
665         hammer2_chain_t *chain;
666         int count = 1000;
667         int i;
668
669         for (i = 0; i < ip->cluster.nchains; ++i) {
670                 chain = ip->cluster.array[i];
671                 if (chain == NULL)
672                         continue;
673                 hammer2_dump_chain(chain, 0, &count, 'i');
674         }
675         return 0;
676 }