Merge branch 'vendor/GDB'
[dragonfly.git] / sys / vfs / hammer2 / hammer2_ioctl.c
1 /*
2  * Copyright (c) 2011-2013 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, 0);
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, 0);
549         error = hammer2_unlink_file(&trans, hmp->sroot,
550                                     pfs->name, strlen(pfs->name),
551                                     2, 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_trans_init(&trans, ip->pmp, 0);
571         parent = hammer2_inode_lock_ex(ip);
572         error = hammer2_chain_snapshot(&trans, parent, pfs);
573         hammer2_inode_unlock_ex(ip, parent);
574         hammer2_trans_done(&trans);
575
576         return (error);
577 }
578
579 /*
580  * Retrieve the raw inode structure
581  */
582 static int
583 hammer2_ioctl_inode_get(hammer2_inode_t *ip, void *data)
584 {
585         hammer2_ioc_inode_t *ino = data;
586         hammer2_chain_t *parent;
587
588         parent = hammer2_inode_lock_sh(ip);
589         ino->ip_data = ip->chain->data->ipdata;
590         ino->kdata = ip;
591         hammer2_inode_unlock_sh(ip, parent);
592
593         return (0);
594 }
595
596 /*
597  * Set various parameters in an inode which cannot be set through
598  * normal filesystem VNOPS.
599  */
600 static int
601 hammer2_ioctl_inode_set(hammer2_inode_t *ip, void *data)
602 {
603         hammer2_inode_data_t *ipdata;
604         hammer2_ioc_inode_t *ino = data;
605         hammer2_chain_t *chain;
606         hammer2_trans_t trans;
607         int error = 0;
608
609         hammer2_trans_init(&trans, ip->pmp, 0);
610         chain = hammer2_inode_lock_ex(ip);
611
612         if (ino->ip_data.comp_algo != chain->data->ipdata.comp_algo) {
613                 ipdata = hammer2_chain_modify_ip(&trans, ip, &chain, 0);
614                 ipdata->comp_algo = ino->ip_data.comp_algo;
615         }
616         ino->kdata = ip;
617         
618         /* Ignore these flags for now...*/
619         if (ino->flags & HAMMER2IOC_INODE_FLAG_IQUOTA) {
620         }
621         if (ino->flags & HAMMER2IOC_INODE_FLAG_DQUOTA) {
622         }
623         if (ino->flags & HAMMER2IOC_INODE_FLAG_COPIES) {
624         }
625         hammer2_trans_done(&trans);
626         hammer2_inode_unlock_ex(ip, chain);
627
628         return (error);
629 }