]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/unionfs/union_subr.c
MFV r348576: 9963 Seperate tunable for disabling ZIL vdev flush
[FreeBSD/FreeBSD.git] / sys / fs / unionfs / union_subr.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1994 Jan-Simon Pendry
5  * Copyright (c) 1994
6  *      The Regents of the University of California.  All rights reserved.
7  * Copyright (c) 2005, 2006, 2012 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc.
8  * Copyright (c) 2006, 2012 Daichi Goto <daichi@freebsd.org>
9  *
10  * This code is derived from software contributed to Berkeley by
11  * Jan-Simon Pendry.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  * 3. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  *      @(#)union_subr.c        8.20 (Berkeley) 5/20/95
38  * $FreeBSD$
39  */
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/kernel.h>
44 #include <sys/ktr.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/malloc.h>
48 #include <sys/mount.h>
49 #include <sys/namei.h>
50 #include <sys/proc.h>
51 #include <sys/vnode.h>
52 #include <sys/dirent.h>
53 #include <sys/fcntl.h>
54 #include <sys/filedesc.h>
55 #include <sys/stat.h>
56 #include <sys/resourcevar.h>
57
58 #include <security/mac/mac_framework.h>
59
60 #include <vm/uma.h>
61
62 #include <fs/unionfs/union.h>
63
64 #define NUNIONFSNODECACHE 16
65
66 static MALLOC_DEFINE(M_UNIONFSHASH, "UNIONFS hash", "UNIONFS hash table");
67 MALLOC_DEFINE(M_UNIONFSNODE, "UNIONFS node", "UNIONFS vnode private part");
68 MALLOC_DEFINE(M_UNIONFSPATH, "UNIONFS path", "UNIONFS path private part");
69
70 /*
71  * Initialize
72  */
73 int 
74 unionfs_init(struct vfsconf *vfsp)
75 {
76         UNIONFSDEBUG("unionfs_init\n"); /* printed during system boot */
77         return (0);
78 }
79
80 /*
81  * Uninitialize
82  */
83 int 
84 unionfs_uninit(struct vfsconf *vfsp)
85 {
86         return (0);
87 }
88
89 static struct unionfs_node_hashhead *
90 unionfs_get_hashhead(struct vnode *dvp, char *path)
91 {
92         int             count;
93         char            hash;
94         struct unionfs_node *unp;
95
96         hash = 0;
97         unp = VTOUNIONFS(dvp);
98         if (path != NULL) {
99                 for (count = 0; path[count]; count++)
100                         hash += path[count];
101         }
102
103         return (&(unp->un_hashtbl[hash & (unp->un_hashmask)]));
104 }
105
106 /*
107  * Get the cached vnode.
108  */
109 static struct vnode *
110 unionfs_get_cached_vnode(struct vnode *uvp, struct vnode *lvp,
111                         struct vnode *dvp, char *path)
112 {
113         struct unionfs_node_hashhead *hd;
114         struct unionfs_node *unp;
115         struct vnode   *vp;
116
117         KASSERT((uvp == NULLVP || uvp->v_type == VDIR),
118             ("unionfs_get_cached_vnode: v_type != VDIR"));
119         KASSERT((lvp == NULLVP || lvp->v_type == VDIR),
120             ("unionfs_get_cached_vnode: v_type != VDIR"));
121
122         VI_LOCK(dvp);
123         hd = unionfs_get_hashhead(dvp, path);
124         LIST_FOREACH(unp, hd, un_hash) {
125                 if (!strcmp(unp->un_path, path)) {
126                         vp = UNIONFSTOV(unp);
127                         VI_LOCK_FLAGS(vp, MTX_DUPOK);
128                         VI_UNLOCK(dvp);
129                         vp->v_iflag &= ~VI_OWEINACT;
130                         if ((vp->v_iflag & (VI_DOOMED | VI_DOINGINACT)) != 0) {
131                                 VI_UNLOCK(vp);
132                                 vp = NULLVP;
133                         } else
134                                 VI_UNLOCK(vp);
135                         return (vp);
136                 }
137         }
138         VI_UNLOCK(dvp);
139
140         return (NULLVP);
141 }
142
143 /*
144  * Add the new vnode into cache.
145  */
146 static struct vnode *
147 unionfs_ins_cached_vnode(struct unionfs_node *uncp,
148                         struct vnode *dvp, char *path)
149 {
150         struct unionfs_node_hashhead *hd;
151         struct unionfs_node *unp;
152         struct vnode   *vp;
153
154         KASSERT((uncp->un_uppervp==NULLVP || uncp->un_uppervp->v_type==VDIR),
155             ("unionfs_ins_cached_vnode: v_type != VDIR"));
156         KASSERT((uncp->un_lowervp==NULLVP || uncp->un_lowervp->v_type==VDIR),
157             ("unionfs_ins_cached_vnode: v_type != VDIR"));
158
159         VI_LOCK(dvp);
160         hd = unionfs_get_hashhead(dvp, path);
161         LIST_FOREACH(unp, hd, un_hash) {
162                 if (!strcmp(unp->un_path, path)) {
163                         vp = UNIONFSTOV(unp);
164                         VI_LOCK_FLAGS(vp, MTX_DUPOK);
165                         vp->v_iflag &= ~VI_OWEINACT;
166                         if ((vp->v_iflag & (VI_DOOMED | VI_DOINGINACT)) != 0) {
167                                 LIST_INSERT_HEAD(hd, uncp, un_hash);
168                                 VI_UNLOCK(vp);
169                                 vp = NULLVP;
170                         } else
171                                 VI_UNLOCK(vp);
172                         VI_UNLOCK(dvp);
173                         return (vp);
174                 }
175         }
176
177         LIST_INSERT_HEAD(hd, uncp, un_hash);
178         VI_UNLOCK(dvp);
179
180         return (NULLVP);
181 }
182
183 /*
184  * Remove the vnode.
185  */
186 static void
187 unionfs_rem_cached_vnode(struct unionfs_node *unp, struct vnode *dvp)
188 {
189         KASSERT((unp != NULL), ("unionfs_rem_cached_vnode: null node"));
190         KASSERT((dvp != NULLVP),
191             ("unionfs_rem_cached_vnode: null parent vnode"));
192         KASSERT((unp->un_hash.le_prev != NULL),
193             ("unionfs_rem_cached_vnode: null hash"));
194
195         VI_LOCK(dvp);
196         LIST_REMOVE(unp, un_hash);
197         unp->un_hash.le_next = NULL;
198         unp->un_hash.le_prev = NULL;
199         VI_UNLOCK(dvp);
200 }
201
202 /*
203  * Make a new or get existing unionfs node.
204  * 
205  * uppervp and lowervp should be unlocked. Because if new unionfs vnode is
206  * locked, uppervp or lowervp is locked too. In order to prevent dead lock,
207  * you should not lock plurality simultaneously.
208  */
209 int
210 unionfs_nodeget(struct mount *mp, struct vnode *uppervp,
211                 struct vnode *lowervp, struct vnode *dvp,
212                 struct vnode **vpp, struct componentname *cnp,
213                 struct thread *td)
214 {
215         struct unionfs_mount *ump;
216         struct unionfs_node *unp;
217         struct vnode   *vp;
218         int             error;
219         int             lkflags;
220         enum vtype      vt;
221         char           *path;
222
223         ump = MOUNTTOUNIONFSMOUNT(mp);
224         lkflags = (cnp ? cnp->cn_lkflags : 0);
225         path = (cnp ? cnp->cn_nameptr : NULL);
226         *vpp = NULLVP;
227
228         if (uppervp == NULLVP && lowervp == NULLVP)
229                 panic("unionfs_nodeget: upper and lower is null");
230
231         vt = (uppervp != NULLVP ? uppervp->v_type : lowervp->v_type);
232
233         /* If it has no ISLASTCN flag, path check is skipped. */
234         if (cnp && !(cnp->cn_flags & ISLASTCN))
235                 path = NULL;
236
237         /* check the cache */
238         if (path != NULL && dvp != NULLVP && vt == VDIR) {
239                 vp = unionfs_get_cached_vnode(uppervp, lowervp, dvp, path);
240                 if (vp != NULLVP) {
241                         vref(vp);
242                         *vpp = vp;
243                         goto unionfs_nodeget_out;
244                 }
245         }
246
247         if ((uppervp == NULLVP || ump->um_uppervp != uppervp) ||
248             (lowervp == NULLVP || ump->um_lowervp != lowervp)) {
249                 /* dvp will be NULLVP only in case of root vnode. */
250                 if (dvp == NULLVP)
251                         return (EINVAL);
252         }
253         unp = malloc(sizeof(struct unionfs_node),
254             M_UNIONFSNODE, M_WAITOK | M_ZERO);
255
256         error = getnewvnode("unionfs", mp, &unionfs_vnodeops, &vp);
257         if (error != 0) {
258                 free(unp, M_UNIONFSNODE);
259                 return (error);
260         }
261         error = insmntque(vp, mp);      /* XXX: Too early for mpsafe fs */
262         if (error != 0) {
263                 free(unp, M_UNIONFSNODE);
264                 return (error);
265         }
266         if (dvp != NULLVP)
267                 vref(dvp);
268         if (uppervp != NULLVP)
269                 vref(uppervp);
270         if (lowervp != NULLVP)
271                 vref(lowervp);
272
273         if (vt == VDIR)
274                 unp->un_hashtbl = hashinit(NUNIONFSNODECACHE, M_UNIONFSHASH,
275                     &(unp->un_hashmask));
276
277         unp->un_vnode = vp;
278         unp->un_uppervp = uppervp;
279         unp->un_lowervp = lowervp;
280         unp->un_dvp = dvp;
281         if (uppervp != NULLVP)
282                 vp->v_vnlock = uppervp->v_vnlock;
283         else
284                 vp->v_vnlock = lowervp->v_vnlock;
285
286         if (path != NULL) {
287                 unp->un_path = (char *)
288                     malloc(cnp->cn_namelen +1, M_UNIONFSPATH, M_WAITOK|M_ZERO);
289                 bcopy(cnp->cn_nameptr, unp->un_path, cnp->cn_namelen);
290                 unp->un_path[cnp->cn_namelen] = '\0';
291         }
292         vp->v_type = vt;
293         vp->v_data = unp;
294
295         if ((uppervp != NULLVP && ump->um_uppervp == uppervp) &&
296             (lowervp != NULLVP && ump->um_lowervp == lowervp))
297                 vp->v_vflag |= VV_ROOT;
298
299         if (path != NULL && dvp != NULLVP && vt == VDIR)
300                 *vpp = unionfs_ins_cached_vnode(unp, dvp, path);
301         if ((*vpp) != NULLVP) {
302                 if (dvp != NULLVP)
303                         vrele(dvp);
304                 if (uppervp != NULLVP)
305                         vrele(uppervp);
306                 if (lowervp != NULLVP)
307                         vrele(lowervp);
308
309                 unp->un_uppervp = NULLVP;
310                 unp->un_lowervp = NULLVP;
311                 unp->un_dvp = NULLVP;
312                 vrele(vp);
313                 vp = *vpp;
314                 vref(vp);
315         } else
316                 *vpp = vp;
317
318 unionfs_nodeget_out:
319         if (lkflags & LK_TYPE_MASK)
320                 vn_lock(vp, lkflags | LK_RETRY);
321
322         return (0);
323 }
324
325 /*
326  * Clean up the unionfs node.
327  */
328 void
329 unionfs_noderem(struct vnode *vp, struct thread *td)
330 {
331         int             count;
332         struct unionfs_node *unp, *unp_t1, *unp_t2;
333         struct unionfs_node_hashhead *hd;
334         struct unionfs_node_status *unsp, *unsp_tmp;
335         struct vnode   *lvp;
336         struct vnode   *uvp;
337         struct vnode   *dvp;
338
339         /*
340          * Use the interlock to protect the clearing of v_data to
341          * prevent faults in unionfs_lock().
342          */
343         VI_LOCK(vp);
344         unp = VTOUNIONFS(vp);
345         lvp = unp->un_lowervp;
346         uvp = unp->un_uppervp;
347         dvp = unp->un_dvp;
348         unp->un_lowervp = unp->un_uppervp = NULLVP;
349         vp->v_vnlock = &(vp->v_lock);
350         vp->v_data = NULL;
351         vp->v_object = NULL;
352         VI_UNLOCK(vp);
353
354         if (lvp != NULLVP)
355                 VOP_UNLOCK(lvp, LK_RELEASE);
356         if (uvp != NULLVP)
357                 VOP_UNLOCK(uvp, LK_RELEASE);
358
359         if (dvp != NULLVP && unp->un_hash.le_prev != NULL)
360                 unionfs_rem_cached_vnode(unp, dvp);
361
362         if (lockmgr(vp->v_vnlock, LK_EXCLUSIVE, VI_MTX(vp)) != 0)
363                 panic("the lock for deletion is unacquirable.");
364
365         if (lvp != NULLVP)
366                 vrele(lvp);
367         if (uvp != NULLVP)
368                 vrele(uvp);
369         if (dvp != NULLVP) {
370                 vrele(dvp);
371                 unp->un_dvp = NULLVP;
372         }
373         if (unp->un_path != NULL) {
374                 free(unp->un_path, M_UNIONFSPATH);
375                 unp->un_path = NULL;
376         }
377
378         if (unp->un_hashtbl != NULL) {
379                 for (count = 0; count <= unp->un_hashmask; count++) {
380                         hd = unp->un_hashtbl + count;
381                         LIST_FOREACH_SAFE(unp_t1, hd, un_hash, unp_t2) {
382                                 LIST_REMOVE(unp_t1, un_hash);
383                                 unp_t1->un_hash.le_next = NULL;
384                                 unp_t1->un_hash.le_prev = NULL;
385                         }
386                 }
387                 hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, unp->un_hashmask);
388         }
389
390         LIST_FOREACH_SAFE(unsp, &(unp->un_unshead), uns_list, unsp_tmp) {
391                 LIST_REMOVE(unsp, uns_list);
392                 free(unsp, M_TEMP);
393         }
394         free(unp, M_UNIONFSNODE);
395 }
396
397 /*
398  * Get the unionfs node status.
399  * You need exclusive lock this vnode.
400  */
401 void
402 unionfs_get_node_status(struct unionfs_node *unp, struct thread *td,
403                         struct unionfs_node_status **unspp)
404 {
405         struct unionfs_node_status *unsp;
406         pid_t pid = td->td_proc->p_pid;
407
408         KASSERT(NULL != unspp, ("null pointer"));
409         ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status");
410
411         LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) {
412                 if (unsp->uns_pid == pid) {
413                         *unspp = unsp;
414                         return;
415                 }
416         }
417
418         /* create a new unionfs node status */
419         unsp = malloc(sizeof(struct unionfs_node_status),
420             M_TEMP, M_WAITOK | M_ZERO);
421
422         unsp->uns_pid = pid;
423         LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list);
424
425         *unspp = unsp;
426 }
427
428 /*
429  * Remove the unionfs node status, if you can.
430  * You need exclusive lock this vnode.
431  */
432 void
433 unionfs_tryrem_node_status(struct unionfs_node *unp,
434                            struct unionfs_node_status *unsp)
435 {
436         KASSERT(NULL != unsp, ("null pointer"));
437         ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status");
438
439         if (0 < unsp->uns_lower_opencnt || 0 < unsp->uns_upper_opencnt)
440                 return;
441
442         LIST_REMOVE(unsp, uns_list);
443         free(unsp, M_TEMP);
444 }
445
446 /*
447  * Create upper node attr.
448  */
449 void
450 unionfs_create_uppervattr_core(struct unionfs_mount *ump,
451                                struct vattr *lva,
452                                struct vattr *uva,
453                                struct thread *td)
454 {
455         VATTR_NULL(uva);
456         uva->va_type = lva->va_type;
457         uva->va_atime = lva->va_atime;
458         uva->va_mtime = lva->va_mtime;
459         uva->va_ctime = lva->va_ctime;
460
461         switch (ump->um_copymode) {
462         case UNIONFS_TRANSPARENT:
463                 uva->va_mode = lva->va_mode;
464                 uva->va_uid = lva->va_uid;
465                 uva->va_gid = lva->va_gid;
466                 break;
467         case UNIONFS_MASQUERADE:
468                 if (ump->um_uid == lva->va_uid) {
469                         uva->va_mode = lva->va_mode & 077077;
470                         uva->va_mode |= (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile) & 0700;
471                         uva->va_uid = lva->va_uid;
472                         uva->va_gid = lva->va_gid;
473                 } else {
474                         uva->va_mode = (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile);
475                         uva->va_uid = ump->um_uid;
476                         uva->va_gid = ump->um_gid;
477                 }
478                 break;
479         default:                /* UNIONFS_TRADITIONAL */
480                 uva->va_mode = 0777 & ~td->td_proc->p_fd->fd_cmask;
481                 uva->va_uid = ump->um_uid;
482                 uva->va_gid = ump->um_gid;
483                 break;
484         }
485 }
486
487 /*
488  * Create upper node attr.
489  */
490 int
491 unionfs_create_uppervattr(struct unionfs_mount *ump,
492                           struct vnode *lvp,
493                           struct vattr *uva,
494                           struct ucred *cred,
495                           struct thread *td)
496 {
497         int             error;
498         struct vattr    lva;
499
500         if ((error = VOP_GETATTR(lvp, &lva, cred)))
501                 return (error);
502
503         unionfs_create_uppervattr_core(ump, &lva, uva, td);
504
505         return (error);
506 }
507
508 /*
509  * relookup
510  * 
511  * dvp should be locked on entry and will be locked on return.
512  * 
513  * If an error is returned, *vpp will be invalid, otherwise it will hold a
514  * locked, referenced vnode. If *vpp == dvp then remember that only one
515  * LK_EXCLUSIVE lock is held.
516  */
517 int
518 unionfs_relookup(struct vnode *dvp, struct vnode **vpp,
519                  struct componentname *cnp, struct componentname *cn,
520                  struct thread *td, char *path, int pathlen, u_long nameiop)
521 {
522         int     error;
523
524         cn->cn_namelen = pathlen;
525         cn->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
526         bcopy(path, cn->cn_pnbuf, pathlen);
527         cn->cn_pnbuf[pathlen] = '\0';
528
529         cn->cn_nameiop = nameiop;
530         cn->cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN);
531         cn->cn_lkflags = LK_EXCLUSIVE;
532         cn->cn_thread = td;
533         cn->cn_cred = cnp->cn_cred;
534
535         cn->cn_nameptr = cn->cn_pnbuf;
536
537         if (nameiop == DELETE)
538                 cn->cn_flags |= (cnp->cn_flags & (DOWHITEOUT | SAVESTART));
539         else if (RENAME == nameiop)
540                 cn->cn_flags |= (cnp->cn_flags & SAVESTART);
541         else if (nameiop == CREATE)
542                 cn->cn_flags |= NOCACHE;
543
544         vref(dvp);
545         VOP_UNLOCK(dvp, LK_RELEASE);
546
547         if ((error = relookup(dvp, vpp, cn))) {
548                 uma_zfree(namei_zone, cn->cn_pnbuf);
549                 cn->cn_flags &= ~HASBUF;
550                 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
551         } else
552                 vrele(dvp);
553
554         return (error);
555 }
556
557 /*
558  * relookup for CREATE namei operation.
559  *
560  * dvp is unionfs vnode. dvp should be locked.
561  *
562  * If it called 'unionfs_copyfile' function by unionfs_link etc,
563  * VOP_LOOKUP information is broken.
564  * So it need relookup in order to create link etc.
565  */
566 int
567 unionfs_relookup_for_create(struct vnode *dvp, struct componentname *cnp,
568                             struct thread *td)
569 {
570         int     error;
571         struct vnode *udvp;
572         struct vnode *vp;
573         struct componentname cn;
574
575         udvp = UNIONFSVPTOUPPERVP(dvp);
576         vp = NULLVP;
577
578         error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
579             strlen(cnp->cn_nameptr), CREATE);
580         if (error)
581                 return (error);
582
583         if (vp != NULLVP) {
584                 if (udvp == vp)
585                         vrele(vp);
586                 else
587                         vput(vp);
588
589                 error = EEXIST;
590         }
591
592         if (cn.cn_flags & HASBUF) {
593                 uma_zfree(namei_zone, cn.cn_pnbuf);
594                 cn.cn_flags &= ~HASBUF;
595         }
596
597         if (!error) {
598                 cn.cn_flags |= (cnp->cn_flags & HASBUF);
599                 cnp->cn_flags = cn.cn_flags;
600         }
601
602         return (error);
603 }
604
605 /*
606  * relookup for DELETE namei operation.
607  *
608  * dvp is unionfs vnode. dvp should be locked.
609  */
610 int
611 unionfs_relookup_for_delete(struct vnode *dvp, struct componentname *cnp,
612                             struct thread *td)
613 {
614         int     error;
615         struct vnode *udvp;
616         struct vnode *vp;
617         struct componentname cn;
618
619         udvp = UNIONFSVPTOUPPERVP(dvp);
620         vp = NULLVP;
621
622         error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
623             strlen(cnp->cn_nameptr), DELETE);
624         if (error)
625                 return (error);
626
627         if (vp == NULLVP)
628                 error = ENOENT;
629         else {
630                 if (udvp == vp)
631                         vrele(vp);
632                 else
633                         vput(vp);
634         }
635
636         if (cn.cn_flags & HASBUF) {
637                 uma_zfree(namei_zone, cn.cn_pnbuf);
638                 cn.cn_flags &= ~HASBUF;
639         }
640
641         if (!error) {
642                 cn.cn_flags |= (cnp->cn_flags & HASBUF);
643                 cnp->cn_flags = cn.cn_flags;
644         }
645
646         return (error);
647 }
648
649 /*
650  * relookup for RENAME namei operation.
651  *
652  * dvp is unionfs vnode. dvp should be locked.
653  */
654 int
655 unionfs_relookup_for_rename(struct vnode *dvp, struct componentname *cnp,
656                             struct thread *td)
657 {
658         int error;
659         struct vnode *udvp;
660         struct vnode *vp;
661         struct componentname cn;
662
663         udvp = UNIONFSVPTOUPPERVP(dvp);
664         vp = NULLVP;
665
666         error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
667             strlen(cnp->cn_nameptr), RENAME);
668         if (error)
669                 return (error);
670
671         if (vp != NULLVP) {
672                 if (udvp == vp)
673                         vrele(vp);
674                 else
675                         vput(vp);
676         }
677
678         if (cn.cn_flags & HASBUF) {
679                 uma_zfree(namei_zone, cn.cn_pnbuf);
680                 cn.cn_flags &= ~HASBUF;
681         }
682
683         if (!error) {
684                 cn.cn_flags |= (cnp->cn_flags & HASBUF);
685                 cnp->cn_flags = cn.cn_flags;
686         }
687
688         return (error);
689
690 }
691
692 /*
693  * Update the unionfs_node.
694  * 
695  * uvp is new locked upper vnode. unionfs vnode's lock will be exchanged to the
696  * uvp's lock and lower's lock will be unlocked.
697  */
698 static void
699 unionfs_node_update(struct unionfs_node *unp, struct vnode *uvp,
700                     struct thread *td)
701 {
702         unsigned        count, lockrec;
703         struct vnode   *vp;
704         struct vnode   *lvp;
705         struct vnode   *dvp;
706
707         vp = UNIONFSTOV(unp);
708         lvp = unp->un_lowervp;
709         ASSERT_VOP_ELOCKED(lvp, "unionfs_node_update");
710         dvp = unp->un_dvp;
711
712         /*
713          * lock update
714          */
715         VI_LOCK(vp);
716         unp->un_uppervp = uvp;
717         vp->v_vnlock = uvp->v_vnlock;
718         VI_UNLOCK(vp);
719         lockrec = lvp->v_vnlock->lk_recurse;
720         for (count = 0; count < lockrec; count++)
721                 vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY);
722
723         /*
724          * cache update
725          */
726         if (unp->un_path != NULL && dvp != NULLVP && vp->v_type == VDIR) {
727                 static struct unionfs_node_hashhead *hd;
728
729                 VI_LOCK(dvp);
730                 hd = unionfs_get_hashhead(dvp, unp->un_path);
731                 LIST_REMOVE(unp, un_hash);
732                 LIST_INSERT_HEAD(hd, unp, un_hash);
733                 VI_UNLOCK(dvp);
734         }
735 }
736
737 /*
738  * Create a new shadow dir.
739  * 
740  * udvp should be locked on entry and will be locked on return.
741  * 
742  * If no error returned, unp will be updated.
743  */
744 int
745 unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *udvp,
746                     struct unionfs_node *unp, struct componentname *cnp,
747                     struct thread *td)
748 {
749         int             error;
750         struct vnode   *lvp;
751         struct vnode   *uvp;
752         struct vattr    va;
753         struct vattr    lva;
754         struct componentname cn;
755         struct mount   *mp;
756         struct ucred   *cred;
757         struct ucred   *credbk;
758         struct uidinfo *rootinfo;
759
760         if (unp->un_uppervp != NULLVP)
761                 return (EEXIST);
762
763         lvp = unp->un_lowervp;
764         uvp = NULLVP;
765         credbk = cnp->cn_cred;
766
767         /* Authority change to root */
768         rootinfo = uifind((uid_t)0);
769         cred = crdup(cnp->cn_cred);
770         /*
771          * The calls to chgproccnt() are needed to compensate for change_ruid()
772          * calling chgproccnt().
773          */
774         chgproccnt(cred->cr_ruidinfo, 1, 0);
775         change_euid(cred, rootinfo);
776         change_ruid(cred, rootinfo);
777         change_svuid(cred, (uid_t)0);
778         uifree(rootinfo);
779         cnp->cn_cred = cred;
780
781         memset(&cn, 0, sizeof(cn));
782
783         if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred)))
784                 goto unionfs_mkshadowdir_abort;
785
786         if ((error = unionfs_relookup(udvp, &uvp, cnp, &cn, td, cnp->cn_nameptr, cnp->cn_namelen, CREATE)))
787                 goto unionfs_mkshadowdir_abort;
788         if (uvp != NULLVP) {
789                 if (udvp == uvp)
790                         vrele(uvp);
791                 else
792                         vput(uvp);
793
794                 error = EEXIST;
795                 goto unionfs_mkshadowdir_free_out;
796         }
797
798         if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH)))
799                 goto unionfs_mkshadowdir_free_out;
800         unionfs_create_uppervattr_core(ump, &lva, &va, td);
801
802         error = VOP_MKDIR(udvp, &uvp, &cn, &va);
803
804         if (!error) {
805                 unionfs_node_update(unp, uvp, td);
806
807                 /*
808                  * XXX The bug which cannot set uid/gid was corrected.
809                  * Ignore errors.
810                  */
811                 va.va_type = VNON;
812                 VOP_SETATTR(uvp, &va, cn.cn_cred);
813         }
814         vn_finished_write(mp);
815
816 unionfs_mkshadowdir_free_out:
817         if (cn.cn_flags & HASBUF) {
818                 uma_zfree(namei_zone, cn.cn_pnbuf);
819                 cn.cn_flags &= ~HASBUF;
820         }
821
822 unionfs_mkshadowdir_abort:
823         cnp->cn_cred = credbk;
824         chgproccnt(cred->cr_ruidinfo, -1, 0);
825         crfree(cred);
826
827         return (error);
828 }
829
830 /*
831  * Create a new whiteout.
832  * 
833  * dvp should be locked on entry and will be locked on return.
834  */
835 int
836 unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp,
837                    struct thread *td, char *path)
838 {
839         int             error;
840         struct vnode   *wvp;
841         struct componentname cn;
842         struct mount   *mp;
843
844         if (path == NULL)
845                 path = cnp->cn_nameptr;
846
847         wvp = NULLVP;
848         if ((error = unionfs_relookup(dvp, &wvp, cnp, &cn, td, path, strlen(path), CREATE)))
849                 return (error);
850         if (wvp != NULLVP) {
851                 if (cn.cn_flags & HASBUF) {
852                         uma_zfree(namei_zone, cn.cn_pnbuf);
853                         cn.cn_flags &= ~HASBUF;
854                 }
855                 if (dvp == wvp)
856                         vrele(wvp);
857                 else
858                         vput(wvp);
859
860                 return (EEXIST);
861         }
862
863         if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)))
864                 goto unionfs_mkwhiteout_free_out;
865         error = VOP_WHITEOUT(dvp, &cn, CREATE);
866
867         vn_finished_write(mp);
868
869 unionfs_mkwhiteout_free_out:
870         if (cn.cn_flags & HASBUF) {
871                 uma_zfree(namei_zone, cn.cn_pnbuf);
872                 cn.cn_flags &= ~HASBUF;
873         }
874
875         return (error);
876 }
877
878 /*
879  * Create a new vnode for create a new shadow file.
880  * 
881  * If an error is returned, *vpp will be invalid, otherwise it will hold a
882  * locked, referenced and opened vnode.
883  * 
884  * unp is never updated.
885  */
886 static int
887 unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp,
888                            struct unionfs_node *unp, struct vattr *uvap,
889                            struct thread *td)
890 {
891         struct unionfs_mount *ump;
892         struct vnode   *vp;
893         struct vnode   *lvp;
894         struct ucred   *cred;
895         struct vattr    lva;
896         int             fmode;
897         int             error;
898         struct componentname cn;
899
900         ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount);
901         vp = NULLVP;
902         lvp = unp->un_lowervp;
903         cred = td->td_ucred;
904         fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL);
905         error = 0;
906
907         if ((error = VOP_GETATTR(lvp, &lva, cred)) != 0)
908                 return (error);
909         unionfs_create_uppervattr_core(ump, &lva, uvap, td);
910
911         if (unp->un_path == NULL)
912                 panic("unionfs: un_path is null");
913
914         cn.cn_namelen = strlen(unp->un_path);
915         cn.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
916         bcopy(unp->un_path, cn.cn_pnbuf, cn.cn_namelen + 1);
917         cn.cn_nameiop = CREATE;
918         cn.cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN);
919         cn.cn_lkflags = LK_EXCLUSIVE;
920         cn.cn_thread = td;
921         cn.cn_cred = cred;
922         cn.cn_nameptr = cn.cn_pnbuf;
923
924         vref(udvp);
925         if ((error = relookup(udvp, &vp, &cn)) != 0)
926                 goto unionfs_vn_create_on_upper_free_out2;
927         vrele(udvp);
928
929         if (vp != NULLVP) {
930                 if (vp == udvp)
931                         vrele(vp);
932                 else
933                         vput(vp);
934                 error = EEXIST;
935                 goto unionfs_vn_create_on_upper_free_out1;
936         }
937
938         if ((error = VOP_CREATE(udvp, &vp, &cn, uvap)) != 0)
939                 goto unionfs_vn_create_on_upper_free_out1;
940
941         if ((error = VOP_OPEN(vp, fmode, cred, td, NULL)) != 0) {
942                 vput(vp);
943                 goto unionfs_vn_create_on_upper_free_out1;
944         }
945         error = VOP_ADD_WRITECOUNT(vp, 1);
946         CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d",  __func__, vp,
947             vp->v_writecount);
948         if (error == 0) {
949                 *vpp = vp;
950         } else {
951                 VOP_CLOSE(vp, fmode, cred, td);
952         }
953
954 unionfs_vn_create_on_upper_free_out1:
955         VOP_UNLOCK(udvp, LK_RELEASE);
956
957 unionfs_vn_create_on_upper_free_out2:
958         if (cn.cn_flags & HASBUF) {
959                 uma_zfree(namei_zone, cn.cn_pnbuf);
960                 cn.cn_flags &= ~HASBUF;
961         }
962
963         return (error);
964 }
965
966 /*
967  * Copy from lvp to uvp.
968  * 
969  * lvp and uvp should be locked and opened on entry and will be locked and
970  * opened on return.
971  */
972 static int
973 unionfs_copyfile_core(struct vnode *lvp, struct vnode *uvp,
974                       struct ucred *cred, struct thread *td)
975 {
976         int             error;
977         off_t           offset;
978         int             count;
979         int             bufoffset;
980         char           *buf;
981         struct uio      uio;
982         struct iovec    iov;
983
984         error = 0;
985         memset(&uio, 0, sizeof(uio));
986
987         uio.uio_td = td;
988         uio.uio_segflg = UIO_SYSSPACE;
989         uio.uio_offset = 0;
990
991         buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
992
993         while (error == 0) {
994                 offset = uio.uio_offset;
995
996                 uio.uio_iov = &iov;
997                 uio.uio_iovcnt = 1;
998                 iov.iov_base = buf;
999                 iov.iov_len = MAXBSIZE;
1000                 uio.uio_resid = iov.iov_len;
1001                 uio.uio_rw = UIO_READ;
1002
1003                 if ((error = VOP_READ(lvp, &uio, 0, cred)) != 0)
1004                         break;
1005                 if ((count = MAXBSIZE - uio.uio_resid) == 0)
1006                         break;
1007
1008                 bufoffset = 0;
1009                 while (bufoffset < count) {
1010                         uio.uio_iov = &iov;
1011                         uio.uio_iovcnt = 1;
1012                         iov.iov_base = buf + bufoffset;
1013                         iov.iov_len = count - bufoffset;
1014                         uio.uio_offset = offset + bufoffset;
1015                         uio.uio_resid = iov.iov_len;
1016                         uio.uio_rw = UIO_WRITE;
1017
1018                         if ((error = VOP_WRITE(uvp, &uio, 0, cred)) != 0)
1019                                 break;
1020
1021                         bufoffset += (count - bufoffset) - uio.uio_resid;
1022                 }
1023
1024                 uio.uio_offset = offset + bufoffset;
1025         }
1026
1027         free(buf, M_TEMP);
1028
1029         return (error);
1030 }
1031
1032 /*
1033  * Copy file from lower to upper.
1034  * 
1035  * If you need copy of the contents, set 1 to docopy. Otherwise, set 0 to
1036  * docopy.
1037  * 
1038  * If no error returned, unp will be updated.
1039  */
1040 int
1041 unionfs_copyfile(struct unionfs_node *unp, int docopy, struct ucred *cred,
1042                  struct thread *td)
1043 {
1044         int             error;
1045         struct mount   *mp;
1046         struct vnode   *udvp;
1047         struct vnode   *lvp;
1048         struct vnode   *uvp;
1049         struct vattr    uva;
1050
1051         lvp = unp->un_lowervp;
1052         uvp = NULLVP;
1053
1054         if ((UNIONFSTOV(unp)->v_mount->mnt_flag & MNT_RDONLY))
1055                 return (EROFS);
1056         if (unp->un_dvp == NULLVP)
1057                 return (EINVAL);
1058         if (unp->un_uppervp != NULLVP)
1059                 return (EEXIST);
1060         udvp = VTOUNIONFS(unp->un_dvp)->un_uppervp;
1061         if (udvp == NULLVP)
1062                 return (EROFS);
1063         if ((udvp->v_mount->mnt_flag & MNT_RDONLY))
1064                 return (EROFS);
1065
1066         error = VOP_ACCESS(lvp, VREAD, cred, td);
1067         if (error != 0)
1068                 return (error);
1069
1070         if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH)) != 0)
1071                 return (error);
1072         error = unionfs_vn_create_on_upper(&uvp, udvp, unp, &uva, td);
1073         if (error != 0) {
1074                 vn_finished_write(mp);
1075                 return (error);
1076         }
1077
1078         if (docopy != 0) {
1079                 error = VOP_OPEN(lvp, FREAD, cred, td, NULL);
1080                 if (error == 0) {
1081                         error = unionfs_copyfile_core(lvp, uvp, cred, td);
1082                         VOP_CLOSE(lvp, FREAD, cred, td);
1083                 }
1084         }
1085         VOP_CLOSE(uvp, FWRITE, cred, td);
1086         VOP_ADD_WRITECOUNT_CHECKED(uvp, -1);
1087         CTR3(KTR_VFS, "%s: vp %p v_writecount decreased to %d", __func__, uvp,
1088             uvp->v_writecount);
1089
1090         vn_finished_write(mp);
1091
1092         if (error == 0) {
1093                 /* Reset the attributes. Ignore errors. */
1094                 uva.va_type = VNON;
1095                 VOP_SETATTR(uvp, &uva, cred);
1096         }
1097
1098         unionfs_node_update(unp, uvp, td);
1099
1100         return (error);
1101 }
1102
1103 /*
1104  * It checks whether vp can rmdir. (check empty)
1105  *
1106  * vp is unionfs vnode.
1107  * vp should be locked.
1108  */
1109 int
1110 unionfs_check_rmdir(struct vnode *vp, struct ucred *cred, struct thread *td)
1111 {
1112         int             error;
1113         int             eofflag;
1114         int             lookuperr;
1115         struct vnode   *uvp;
1116         struct vnode   *lvp;
1117         struct vnode   *tvp;
1118         struct vattr    va;
1119         struct componentname cn;
1120         /*
1121          * The size of buf needs to be larger than DIRBLKSIZ.
1122          */
1123         char            buf[256 * 6];
1124         struct dirent  *dp;
1125         struct dirent  *edp;
1126         struct uio      uio;
1127         struct iovec    iov;
1128
1129         ASSERT_VOP_ELOCKED(vp, "unionfs_check_rmdir");
1130
1131         eofflag = 0;
1132         uvp = UNIONFSVPTOUPPERVP(vp);
1133         lvp = UNIONFSVPTOLOWERVP(vp);
1134
1135         /* check opaque */
1136         if ((error = VOP_GETATTR(uvp, &va, cred)) != 0)
1137                 return (error);
1138         if (va.va_flags & OPAQUE)
1139                 return (0);
1140
1141         /* open vnode */
1142 #ifdef MAC
1143         if ((error = mac_vnode_check_open(cred, vp, VEXEC|VREAD)) != 0)
1144                 return (error);
1145 #endif
1146         if ((error = VOP_ACCESS(vp, VEXEC|VREAD, cred, td)) != 0)
1147                 return (error);
1148         if ((error = VOP_OPEN(vp, FREAD, cred, td, NULL)) != 0)
1149                 return (error);
1150
1151         uio.uio_rw = UIO_READ;
1152         uio.uio_segflg = UIO_SYSSPACE;
1153         uio.uio_td = td;
1154         uio.uio_offset = 0;
1155
1156 #ifdef MAC
1157         error = mac_vnode_check_readdir(td->td_ucred, lvp);
1158 #endif
1159         while (!error && !eofflag) {
1160                 iov.iov_base = buf;
1161                 iov.iov_len = sizeof(buf);
1162                 uio.uio_iov = &iov;
1163                 uio.uio_iovcnt = 1;
1164                 uio.uio_resid = iov.iov_len;
1165
1166                 error = VOP_READDIR(lvp, &uio, cred, &eofflag, NULL, NULL);
1167                 if (error != 0)
1168                         break;
1169                 if (eofflag == 0 && uio.uio_resid == sizeof(buf)) {
1170 #ifdef DIAGNOSTIC
1171                         panic("bad readdir response from lower FS.");
1172 #endif
1173                         break;
1174                 }
1175
1176                 edp = (struct dirent*)&buf[sizeof(buf) - uio.uio_resid];
1177                 for (dp = (struct dirent*)buf; !error && dp < edp;
1178                      dp = (struct dirent*)((caddr_t)dp + dp->d_reclen)) {
1179                         if (dp->d_type == DT_WHT || dp->d_fileno == 0 ||
1180                             (dp->d_namlen == 1 && dp->d_name[0] == '.') ||
1181                             (dp->d_namlen == 2 && !bcmp(dp->d_name, "..", 2)))
1182                                 continue;
1183
1184                         cn.cn_namelen = dp->d_namlen;
1185                         cn.cn_pnbuf = NULL;
1186                         cn.cn_nameptr = dp->d_name;
1187                         cn.cn_nameiop = LOOKUP;
1188                         cn.cn_flags = (LOCKPARENT | LOCKLEAF | SAVENAME | RDONLY | ISLASTCN);
1189                         cn.cn_lkflags = LK_EXCLUSIVE;
1190                         cn.cn_thread = td;
1191                         cn.cn_cred = cred;
1192
1193                         /*
1194                          * check entry in lower.
1195                          * Sometimes, readdir function returns
1196                          * wrong entry.
1197                          */
1198                         lookuperr = VOP_LOOKUP(lvp, &tvp, &cn);
1199
1200                         if (!lookuperr)
1201                                 vput(tvp);
1202                         else
1203                                 continue; /* skip entry */
1204
1205                         /*
1206                          * check entry
1207                          * If it has no exist/whiteout entry in upper,
1208                          * directory is not empty.
1209                          */
1210                         cn.cn_flags = (LOCKPARENT | LOCKLEAF | SAVENAME | RDONLY | ISLASTCN);
1211                         lookuperr = VOP_LOOKUP(uvp, &tvp, &cn);
1212
1213                         if (!lookuperr)
1214                                 vput(tvp);
1215
1216                         /* ignore exist or whiteout entry */
1217                         if (!lookuperr ||
1218                             (lookuperr == ENOENT && (cn.cn_flags & ISWHITEOUT)))
1219                                 continue;
1220
1221                         error = ENOTEMPTY;
1222                 }
1223         }
1224
1225         /* close vnode */
1226         VOP_CLOSE(vp, FREAD, cred, td);
1227
1228         return (error);
1229 }
1230
1231 #ifdef DIAGNOSTIC
1232
1233 struct vnode   *
1234 unionfs_checkuppervp(struct vnode *vp, char *fil, int lno)
1235 {
1236         struct unionfs_node *unp;
1237
1238         unp = VTOUNIONFS(vp);
1239
1240 #ifdef notyet
1241         if (vp->v_op != unionfs_vnodeop_p) {
1242                 printf("unionfs_checkuppervp: on non-unionfs-node.\n");
1243 #ifdef KDB
1244                 kdb_enter(KDB_WHY_UNIONFS,
1245                     "unionfs_checkuppervp: on non-unionfs-node.\n");
1246 #endif
1247                 panic("unionfs_checkuppervp");
1248         }
1249 #endif
1250         return (unp->un_uppervp);
1251 }
1252
1253 struct vnode   *
1254 unionfs_checklowervp(struct vnode *vp, char *fil, int lno)
1255 {
1256         struct unionfs_node *unp;
1257
1258         unp = VTOUNIONFS(vp);
1259
1260 #ifdef notyet
1261         if (vp->v_op != unionfs_vnodeop_p) {
1262                 printf("unionfs_checklowervp: on non-unionfs-node.\n");
1263 #ifdef KDB
1264                 kdb_enter(KDB_WHY_UNIONFS,
1265                     "unionfs_checklowervp: on non-unionfs-node.\n");
1266 #endif
1267                 panic("unionfs_checklowervp");
1268         }
1269 #endif
1270         return (unp->un_lowervp);
1271 }
1272 #endif