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