xref: /dragonfly/sys/vfs/hammer2/hammer2_ioctl.c (revision 33311965)
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.chains[0]->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.chains[0]->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.chains[0]->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.chains[0]->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.chains[0]->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.chains[0]->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_chain_t *parent;
356 	hammer2_chain_t *chain;
357 	hammer2_chain_t *rchain;
358 	hammer2_key_t key_next;
359 	int error;
360 	int cache_index = -1;
361 
362 	error = 0;
363 	hmp = ip->pmp->cluster.chains[0]->hmp; /* XXX */
364 	pfs = data;
365 	parent = hammer2_inode_lock_ex(hmp->sroot);
366 	rchain = 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 		chain = hammer2_chain_lookup(&parent, &key_next,
374 					     0, (hammer2_key_t)-1,
375 					     &cache_index, 0);
376 	} else if (pfs->name_key == (hammer2_key_t)-1) {
377 		chain = hammer2_chain_lookup(&parent, &key_next,
378 					     rchain->data->ipdata.name_key,
379 					     rchain->data->ipdata.name_key,
380 					     &cache_index, 0);
381 	} else {
382 		chain = hammer2_chain_lookup(&parent, &key_next,
383 					     pfs->name_key, pfs->name_key,
384 					     &cache_index, 0);
385 	}
386 	hammer2_inode_unlock_ex(ip->pmp->iroot, rchain);
387 
388 	while (chain && chain->bref.type != HAMMER2_BREF_TYPE_INODE) {
389 		chain = hammer2_chain_next(&parent, chain, &key_next,
390 					   key_next, (hammer2_key_t)-1,
391 					   &cache_index, 0);
392 	}
393 	if (chain) {
394 		/*
395 		 * Load the data being returned by the ioctl.
396 		 */
397 		ipdata = &chain->data->ipdata;
398 		pfs->name_key = ipdata->name_key;
399 		pfs->pfs_type = ipdata->pfs_type;
400 		pfs->pfs_clid = ipdata->pfs_clid;
401 		pfs->pfs_fsid = ipdata->pfs_fsid;
402 		KKASSERT(ipdata->name_len < sizeof(pfs->name));
403 		bcopy(ipdata->filename, pfs->name, ipdata->name_len);
404 		pfs->name[ipdata->name_len] = 0;
405 		ipdata = NULL;	/* safety */
406 
407 		/*
408 		 * Calculate the next field
409 		 */
410 		do {
411 			chain = hammer2_chain_next(&parent, chain, &key_next,
412 						   0, (hammer2_key_t)-1,
413 						   &cache_index, 0);
414 		} while (chain && chain->bref.type != HAMMER2_BREF_TYPE_INODE);
415 		if (chain) {
416 			pfs->name_next = chain->data->ipdata.name_key;
417 			hammer2_chain_unlock(chain);
418 		} else {
419 			pfs->name_next = (hammer2_key_t)-1;
420 		}
421 	} else {
422 		pfs->name_next = (hammer2_key_t)-1;
423 		error = ENOENT;
424 	}
425 	hammer2_inode_unlock_ex(hmp->sroot, parent);
426 
427 	return (error);
428 }
429 
430 /*
431  * Find a specific PFS by name
432  */
433 static int
434 hammer2_ioctl_pfs_lookup(hammer2_inode_t *ip, void *data)
435 {
436 	hammer2_inode_data_t *ipdata;
437 	hammer2_mount_t *hmp;
438 	hammer2_ioc_pfs_t *pfs;
439 	hammer2_chain_t *parent;
440 	hammer2_chain_t *chain;
441 	hammer2_key_t key_next;
442 	hammer2_key_t lhc;
443 	int error;
444 	int cache_index = -1;
445 	size_t len;
446 
447 	error = 0;
448 	hmp = ip->pmp->cluster.chains[0]->hmp; /* XXX */
449 	pfs = data;
450 	parent = hammer2_inode_lock_sh(hmp->sroot);
451 
452 	pfs->name[sizeof(pfs->name) - 1] = 0;
453 	len = strlen(pfs->name);
454 	lhc = hammer2_dirhash(pfs->name, len);
455 
456 	chain = hammer2_chain_lookup(&parent, &key_next,
457 				     lhc, lhc + HAMMER2_DIRHASH_LOMASK,
458 				     &cache_index, HAMMER2_LOOKUP_SHARED);
459 	while (chain) {
460 		if (chain->bref.type == HAMMER2_BREF_TYPE_INODE &&
461 		    len == chain->data->ipdata.name_len &&
462 		    bcmp(pfs->name, chain->data->ipdata.filename, len) == 0) {
463 			break;
464 		}
465 		chain = hammer2_chain_next(&parent, chain, &key_next,
466 					   key_next,
467 					   lhc + HAMMER2_DIRHASH_LOMASK,
468 					   &cache_index, HAMMER2_LOOKUP_SHARED);
469 	}
470 
471 	/*
472 	 * Load the data being returned by the ioctl.
473 	 */
474 	if (chain) {
475 		ipdata = &chain->data->ipdata;
476 		pfs->name_key = ipdata->name_key;
477 		pfs->pfs_type = ipdata->pfs_type;
478 		pfs->pfs_clid = ipdata->pfs_clid;
479 		pfs->pfs_fsid = ipdata->pfs_fsid;
480 		ipdata = NULL;
481 
482 		hammer2_chain_unlock(chain);
483 	} else {
484 		error = ENOENT;
485 	}
486 	hammer2_inode_unlock_sh(hmp->sroot, parent);
487 
488 	return (error);
489 }
490 
491 /*
492  * Create a new PFS under the super-root
493  */
494 static int
495 hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data)
496 {
497 	hammer2_inode_data_t *nipdata;
498 	hammer2_mount_t *hmp;
499 	hammer2_ioc_pfs_t *pfs;
500 	hammer2_inode_t *nip;
501 	hammer2_chain_t *nchain;
502 	hammer2_trans_t trans;
503 	int error;
504 
505 	hmp = ip->pmp->cluster.chains[0]->hmp; /* XXX */
506 	pfs = data;
507 	nip = NULL;
508 
509 	if (pfs->name[0] == 0)
510 		return(EINVAL);
511 	pfs->name[sizeof(pfs->name) - 1] = 0;	/* ensure 0-termination */
512 
513 	hammer2_trans_init(&trans, ip->pmp, NULL, HAMMER2_TRANS_NEWINODE);
514 	nip = hammer2_inode_create(&trans, hmp->sroot, NULL, NULL,
515 				     pfs->name, strlen(pfs->name),
516 				     &nchain, &error);
517 	if (error == 0) {
518 		nipdata = hammer2_chain_modify_ip(&trans, nip, &nchain,
519 						  HAMMER2_MODIFY_ASSERTNOCOPY);
520 		nipdata->pfs_type = pfs->pfs_type;
521 		nipdata->pfs_clid = pfs->pfs_clid;
522 		nipdata->pfs_fsid = pfs->pfs_fsid;
523 
524 		/*
525 		 * Do not allow compression on PFS's with the special name
526 		 * "boot", the boot loader can't decompress (yet).
527 		 */
528 		if (strcmp(pfs->name, "boot") == 0)
529 			nipdata->comp_algo = HAMMER2_COMP_AUTOZERO;
530 		hammer2_inode_unlock_ex(nip, nchain);
531 	}
532 	hammer2_trans_done(&trans);
533 	return (error);
534 }
535 
536 /*
537  * Destroy an existing PFS under the super-root
538  */
539 static int
540 hammer2_ioctl_pfs_delete(hammer2_inode_t *ip, void *data)
541 {
542 	hammer2_mount_t *hmp;
543 	hammer2_ioc_pfs_t *pfs = data;
544 	hammer2_trans_t trans;
545 	int error;
546 
547 	hmp = ip->pmp->cluster.chains[0]->hmp; /* XXX */
548 	hammer2_trans_init(&trans, ip->pmp, NULL, 0);
549 	error = hammer2_unlink_file(&trans, hmp->sroot,
550 				    pfs->name, strlen(pfs->name),
551 				    2, NULL, NULL);
552 	hammer2_trans_done(&trans);
553 
554 	return (error);
555 }
556 
557 static int
558 hammer2_ioctl_pfs_snapshot(hammer2_inode_t *ip, void *data)
559 {
560 	hammer2_ioc_pfs_t *pfs = data;
561 	hammer2_trans_t trans;
562 	hammer2_chain_t *parent;
563 	int error;
564 
565 	if (pfs->name[0] == 0)
566 		return(EINVAL);
567 	if (pfs->name[sizeof(pfs->name)-1] != 0)
568 		return(EINVAL);
569 
570 	hammer2_vfs_sync(ip->pmp->mp, MNT_WAIT);
571 
572 	hammer2_trans_init(&trans, ip->pmp, NULL, HAMMER2_TRANS_NEWINODE);
573 	parent = hammer2_inode_lock_ex(ip);
574 	error = hammer2_chain_snapshot(&trans, &parent, pfs);
575 	hammer2_inode_unlock_ex(ip, parent);
576 	hammer2_trans_done(&trans);
577 
578 	return (error);
579 }
580 
581 /*
582  * Retrieve the raw inode structure
583  */
584 static int
585 hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data)
586 {
587 	hammer2_ioc_inode_t *ino = data;
588 	hammer2_chain_t *parent;
589 
590 	parent = hammer2_inode_lock_sh(ip);
591 	ino->ip_data = ip->chain->data->ipdata;
592 	ino->kdata = ip;
593 	hammer2_inode_unlock_sh(ip, parent);
594 
595 	return (0);
596 }
597 
598 /*
599  * Set various parameters in an inode which cannot be set through
600  * normal filesystem VNOPS.
601  */
602 static int
603 hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data)
604 {
605 	hammer2_inode_data_t *ipdata;
606 	hammer2_ioc_inode_t *ino = data;
607 	hammer2_chain_t *chain;
608 	hammer2_trans_t trans;
609 	int error = 0;
610 
611 	hammer2_trans_init(&trans, ip->pmp, NULL, 0);
612 	chain = hammer2_inode_lock_ex(ip);
613 
614 	if (ino->ip_data.comp_algo != chain->data->ipdata.comp_algo) {
615 		ipdata = hammer2_chain_modify_ip(&trans, ip, &chain, 0);
616 		ipdata->comp_algo = ino->ip_data.comp_algo;
617 	}
618 	ino->kdata = ip;
619 
620 	/* Ignore these flags for now...*/
621 	if (ino->flags & HAMMER2IOC_INODE_FLAG_IQUOTA) {
622 	}
623 	if (ino->flags & HAMMER2IOC_INODE_FLAG_DQUOTA) {
624 	}
625 	if (ino->flags & HAMMER2IOC_INODE_FLAG_COPIES) {
626 	}
627 	hammer2_trans_done(&trans);
628 	hammer2_inode_unlock_ex(ip, chain);
629 
630 	return (error);
631 }
632