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