]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/fs/unionfs/union_subr.c
The r241025 fixed the case when a binary, executed from nullfs mount,
[FreeBSD/FreeBSD.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, 2012 Masanori Ozawa <ozawa@ongs.co.jp>, ONGS Inc.
6  * Copyright (c) 2006, 2012 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             count;
335         struct unionfs_node *unp, *unp_t1, *unp_t2;
336         struct unionfs_node_hashhead *hd;
337         struct unionfs_node_status *unsp, *unsp_tmp;
338         struct vnode   *lvp;
339         struct vnode   *uvp;
340         struct vnode   *dvp;
341
342         /*
343          * Use the interlock to protect the clearing of v_data to
344          * prevent faults in unionfs_lock().
345          */
346         VI_LOCK(vp);
347         unp = VTOUNIONFS(vp);
348         lvp = unp->un_lowervp;
349         uvp = unp->un_uppervp;
350         dvp = unp->un_dvp;
351         unp->un_lowervp = unp->un_uppervp = NULLVP;
352         vp->v_vnlock = &(vp->v_lock);
353         vp->v_data = NULL;
354         vp->v_object = NULL;
355         VI_UNLOCK(vp);
356
357         if (lvp != NULLVP)
358                 VOP_UNLOCK(lvp, LK_RELEASE);
359         if (uvp != NULLVP)
360                 VOP_UNLOCK(uvp, LK_RELEASE);
361
362         if (dvp != NULLVP && unp->un_hash.le_prev != NULL)
363                 unionfs_rem_cached_vnode(unp, dvp);
364
365         if (lockmgr(vp->v_vnlock, LK_EXCLUSIVE, VI_MTX(vp)) != 0)
366                 panic("the lock for deletion is unacquirable.");
367
368         if (lvp != NULLVP)
369                 vrele(lvp);
370         if (uvp != NULLVP)
371                 vrele(uvp);
372         if (dvp != NULLVP) {
373                 vrele(dvp);
374                 unp->un_dvp = NULLVP;
375         }
376         if (unp->un_path != NULL) {
377                 free(unp->un_path, M_UNIONFSPATH);
378                 unp->un_path = NULL;
379         }
380
381         if (unp->un_hashtbl != NULL) {
382                 for (count = 0; count <= unp->un_hashmask; count++) {
383                         hd = unp->un_hashtbl + count;
384                         LIST_FOREACH_SAFE(unp_t1, hd, un_hash, unp_t2) {
385                                 LIST_REMOVE(unp_t1, un_hash);
386                                 unp_t1->un_hash.le_next = NULL;
387                                 unp_t1->un_hash.le_prev = NULL;
388                         }
389                 }
390                 hashdestroy(unp->un_hashtbl, M_UNIONFSHASH, unp->un_hashmask);
391         }
392
393         LIST_FOREACH_SAFE(unsp, &(unp->un_unshead), uns_list, unsp_tmp) {
394                 LIST_REMOVE(unsp, uns_list);
395                 free(unsp, M_TEMP);
396         }
397         free(unp, M_UNIONFSNODE);
398 }
399
400 /*
401  * Get the unionfs node status.
402  * You need exclusive lock this vnode.
403  */
404 void
405 unionfs_get_node_status(struct unionfs_node *unp, struct thread *td,
406                         struct unionfs_node_status **unspp)
407 {
408         struct unionfs_node_status *unsp;
409         pid_t pid = td->td_proc->p_pid;
410
411         KASSERT(NULL != unspp, ("null pointer"));
412         ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status");
413
414         LIST_FOREACH(unsp, &(unp->un_unshead), uns_list) {
415                 if (unsp->uns_pid == pid) {
416                         *unspp = unsp;
417                         return;
418                 }
419         }
420
421         /* create a new unionfs node status */
422         unsp = malloc(sizeof(struct unionfs_node_status),
423             M_TEMP, M_WAITOK | M_ZERO);
424
425         unsp->uns_pid = pid;
426         LIST_INSERT_HEAD(&(unp->un_unshead), unsp, uns_list);
427
428         *unspp = unsp;
429 }
430
431 /*
432  * Remove the unionfs node status, if you can.
433  * You need exclusive lock this vnode.
434  */
435 void
436 unionfs_tryrem_node_status(struct unionfs_node *unp,
437                            struct unionfs_node_status *unsp)
438 {
439         KASSERT(NULL != unsp, ("null pointer"));
440         ASSERT_VOP_ELOCKED(UNIONFSTOV(unp), "unionfs_get_node_status");
441
442         if (0 < unsp->uns_lower_opencnt || 0 < unsp->uns_upper_opencnt)
443                 return;
444
445         LIST_REMOVE(unsp, uns_list);
446         free(unsp, M_TEMP);
447 }
448
449 /*
450  * Create upper node attr.
451  */
452 void
453 unionfs_create_uppervattr_core(struct unionfs_mount *ump,
454                                struct vattr *lva,
455                                struct vattr *uva,
456                                struct thread *td)
457 {
458         VATTR_NULL(uva);
459         uva->va_type = lva->va_type;
460         uva->va_atime = lva->va_atime;
461         uva->va_mtime = lva->va_mtime;
462         uva->va_ctime = lva->va_ctime;
463
464         switch (ump->um_copymode) {
465         case UNIONFS_TRANSPARENT:
466                 uva->va_mode = lva->va_mode;
467                 uva->va_uid = lva->va_uid;
468                 uva->va_gid = lva->va_gid;
469                 break;
470         case UNIONFS_MASQUERADE:
471                 if (ump->um_uid == lva->va_uid) {
472                         uva->va_mode = lva->va_mode & 077077;
473                         uva->va_mode |= (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile) & 0700;
474                         uva->va_uid = lva->va_uid;
475                         uva->va_gid = lva->va_gid;
476                 } else {
477                         uva->va_mode = (lva->va_type == VDIR ? ump->um_udir : ump->um_ufile);
478                         uva->va_uid = ump->um_uid;
479                         uva->va_gid = ump->um_gid;
480                 }
481                 break;
482         default:                /* UNIONFS_TRADITIONAL */
483                 uva->va_mode = 0777 & ~td->td_proc->p_fd->fd_cmask;
484                 uva->va_uid = ump->um_uid;
485                 uva->va_gid = ump->um_gid;
486                 break;
487         }
488 }
489
490 /*
491  * Create upper node attr.
492  */
493 int
494 unionfs_create_uppervattr(struct unionfs_mount *ump,
495                           struct vnode *lvp,
496                           struct vattr *uva,
497                           struct ucred *cred,
498                           struct thread *td)
499 {
500         int             error;
501         struct vattr    lva;
502
503         if ((error = VOP_GETATTR(lvp, &lva, cred)))
504                 return (error);
505
506         unionfs_create_uppervattr_core(ump, &lva, uva, td);
507
508         return (error);
509 }
510
511 /*
512  * relookup
513  * 
514  * dvp should be locked on entry and will be locked on return.
515  * 
516  * If an error is returned, *vpp will be invalid, otherwise it will hold a
517  * locked, referenced vnode. If *vpp == dvp then remember that only one
518  * LK_EXCLUSIVE lock is held.
519  */
520 int
521 unionfs_relookup(struct vnode *dvp, struct vnode **vpp,
522                  struct componentname *cnp, struct componentname *cn,
523                  struct thread *td, char *path, int pathlen, u_long nameiop)
524 {
525         int     error;
526
527         cn->cn_namelen = pathlen;
528         cn->cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
529         bcopy(path, cn->cn_pnbuf, pathlen);
530         cn->cn_pnbuf[pathlen] = '\0';
531
532         cn->cn_nameiop = nameiop;
533         cn->cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN);
534         cn->cn_lkflags = LK_EXCLUSIVE;
535         cn->cn_thread = td;
536         cn->cn_cred = cnp->cn_cred;
537
538         cn->cn_nameptr = cn->cn_pnbuf;
539         cn->cn_consume = cnp->cn_consume;
540
541         if (nameiop == DELETE)
542                 cn->cn_flags |= (cnp->cn_flags & (DOWHITEOUT | SAVESTART));
543         else if (RENAME == nameiop)
544                 cn->cn_flags |= (cnp->cn_flags & SAVESTART);
545
546         vref(dvp);
547         VOP_UNLOCK(dvp, LK_RELEASE);
548
549         if ((error = relookup(dvp, vpp, cn))) {
550                 uma_zfree(namei_zone, cn->cn_pnbuf);
551                 cn->cn_flags &= ~HASBUF;
552                 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
553         } else
554                 vrele(dvp);
555
556         return (error);
557 }
558
559 /*
560  * relookup for CREATE namei operation.
561  *
562  * dvp is unionfs vnode. dvp should be locked.
563  *
564  * If it called 'unionfs_copyfile' function by unionfs_link etc,
565  * VOP_LOOKUP information is broken.
566  * So it need relookup in order to create link etc.
567  */
568 int
569 unionfs_relookup_for_create(struct vnode *dvp, struct componentname *cnp,
570                             struct thread *td)
571 {
572         int     error;
573         struct vnode *udvp;
574         struct vnode *vp;
575         struct componentname cn;
576
577         udvp = UNIONFSVPTOUPPERVP(dvp);
578         vp = NULLVP;
579
580         error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
581             strlen(cnp->cn_nameptr), CREATE);
582         if (error)
583                 return (error);
584
585         if (vp != NULLVP) {
586                 if (udvp == vp)
587                         vrele(vp);
588                 else
589                         vput(vp);
590
591                 error = EEXIST;
592         }
593
594         if (cn.cn_flags & HASBUF) {
595                 uma_zfree(namei_zone, cn.cn_pnbuf);
596                 cn.cn_flags &= ~HASBUF;
597         }
598
599         if (!error) {
600                 cn.cn_flags |= (cnp->cn_flags & HASBUF);
601                 cnp->cn_flags = cn.cn_flags;
602         }
603
604         return (error);
605 }
606
607 /*
608  * relookup for DELETE namei operation.
609  *
610  * dvp is unionfs vnode. dvp should be locked.
611  */
612 int
613 unionfs_relookup_for_delete(struct vnode *dvp, struct componentname *cnp,
614                             struct thread *td)
615 {
616         int     error;
617         struct vnode *udvp;
618         struct vnode *vp;
619         struct componentname cn;
620
621         udvp = UNIONFSVPTOUPPERVP(dvp);
622         vp = NULLVP;
623
624         error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
625             strlen(cnp->cn_nameptr), DELETE);
626         if (error)
627                 return (error);
628
629         if (vp == NULLVP)
630                 error = ENOENT;
631         else {
632                 if (udvp == vp)
633                         vrele(vp);
634                 else
635                         vput(vp);
636         }
637
638         if (cn.cn_flags & HASBUF) {
639                 uma_zfree(namei_zone, cn.cn_pnbuf);
640                 cn.cn_flags &= ~HASBUF;
641         }
642
643         if (!error) {
644                 cn.cn_flags |= (cnp->cn_flags & HASBUF);
645                 cnp->cn_flags = cn.cn_flags;
646         }
647
648         return (error);
649 }
650
651 /*
652  * relookup for RENAME namei operation.
653  *
654  * dvp is unionfs vnode. dvp should be locked.
655  */
656 int
657 unionfs_relookup_for_rename(struct vnode *dvp, struct componentname *cnp,
658                             struct thread *td)
659 {
660         int error;
661         struct vnode *udvp;
662         struct vnode *vp;
663         struct componentname cn;
664
665         udvp = UNIONFSVPTOUPPERVP(dvp);
666         vp = NULLVP;
667
668         error = unionfs_relookup(udvp, &vp, cnp, &cn, td, cnp->cn_nameptr,
669             strlen(cnp->cn_nameptr), RENAME);
670         if (error)
671                 return (error);
672
673         if (vp != NULLVP) {
674                 if (udvp == vp)
675                         vrele(vp);
676                 else
677                         vput(vp);
678         }
679
680         if (cn.cn_flags & HASBUF) {
681                 uma_zfree(namei_zone, cn.cn_pnbuf);
682                 cn.cn_flags &= ~HASBUF;
683         }
684
685         if (!error) {
686                 cn.cn_flags |= (cnp->cn_flags & HASBUF);
687                 cnp->cn_flags = cn.cn_flags;
688         }
689
690         return (error);
691
692 }
693
694 /*
695  * Update the unionfs_node.
696  * 
697  * uvp is new locked upper vnode. unionfs vnode's lock will be exchanged to the
698  * uvp's lock and lower's lock will be unlocked.
699  */
700 static void
701 unionfs_node_update(struct unionfs_node *unp, struct vnode *uvp,
702                     struct thread *td)
703 {
704         unsigned        count, lockrec;
705         struct vnode   *vp;
706         struct vnode   *lvp;
707         struct vnode   *dvp;
708
709         vp = UNIONFSTOV(unp);
710         lvp = unp->un_lowervp;
711         ASSERT_VOP_ELOCKED(lvp, "unionfs_node_update");
712         dvp = unp->un_dvp;
713
714         /*
715          * lock update
716          */
717         VI_LOCK(vp);
718         unp->un_uppervp = uvp;
719         vp->v_vnlock = uvp->v_vnlock;
720         VI_UNLOCK(vp);
721         lockrec = lvp->v_vnlock->lk_recurse;
722         for (count = 0; count < lockrec; count++)
723                 vn_lock(uvp, LK_EXCLUSIVE | LK_CANRECURSE | LK_RETRY);
724
725         /*
726          * cache update
727          */
728         if (unp->un_path != NULL && dvp != NULLVP && vp->v_type == VDIR) {
729                 static struct unionfs_node_hashhead *hd;
730
731                 VI_LOCK(dvp);
732                 hd = unionfs_get_hashhead(dvp, unp->un_path);
733                 LIST_REMOVE(unp, un_hash);
734                 LIST_INSERT_HEAD(hd, unp, un_hash);
735                 VI_UNLOCK(dvp);
736         }
737 }
738
739 /*
740  * Create a new shadow dir.
741  * 
742  * udvp should be locked on entry and will be locked on return.
743  * 
744  * If no error returned, unp will be updated.
745  */
746 int
747 unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *udvp,
748                     struct unionfs_node *unp, struct componentname *cnp,
749                     struct thread *td)
750 {
751         int             error;
752         struct vnode   *lvp;
753         struct vnode   *uvp;
754         struct vattr    va;
755         struct vattr    lva;
756         struct componentname cn;
757         struct mount   *mp;
758         struct ucred   *cred;
759         struct ucred   *credbk;
760         struct uidinfo *rootinfo;
761
762         if (unp->un_uppervp != NULLVP)
763                 return (EEXIST);
764
765         lvp = unp->un_lowervp;
766         uvp = NULLVP;
767         credbk = cnp->cn_cred;
768
769         /* Authority change to root */
770         rootinfo = uifind((uid_t)0);
771         cred = crdup(cnp->cn_cred);
772         /*
773          * The calls to chgproccnt() are needed to compensate for change_ruid()
774          * calling chgproccnt().
775          */
776         chgproccnt(cred->cr_ruidinfo, 1, 0);
777         change_euid(cred, rootinfo);
778         change_ruid(cred, rootinfo);
779         change_svuid(cred, (uid_t)0);
780         uifree(rootinfo);
781         cnp->cn_cred = cred;
782
783         memset(&cn, 0, sizeof(cn));
784
785         if ((error = VOP_GETATTR(lvp, &lva, cnp->cn_cred)))
786                 goto unionfs_mkshadowdir_abort;
787
788         if ((error = unionfs_relookup(udvp, &uvp, cnp, &cn, td, cnp->cn_nameptr, cnp->cn_namelen, CREATE)))
789                 goto unionfs_mkshadowdir_abort;
790         if (uvp != NULLVP) {
791                 if (udvp == uvp)
792                         vrele(uvp);
793                 else
794                         vput(uvp);
795
796                 error = EEXIST;
797                 goto unionfs_mkshadowdir_free_out;
798         }
799
800         if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH)))
801                 goto unionfs_mkshadowdir_free_out;
802         unionfs_create_uppervattr_core(ump, &lva, &va, td);
803
804         error = VOP_MKDIR(udvp, &uvp, &cn, &va);
805
806         if (!error) {
807                 unionfs_node_update(unp, uvp, td);
808
809                 /*
810                  * XXX The bug which cannot set uid/gid was corrected.
811                  * Ignore errors.
812                  */
813                 va.va_type = VNON;
814                 VOP_SETATTR(uvp, &va, cn.cn_cred);
815         }
816         vn_finished_write(mp);
817
818 unionfs_mkshadowdir_free_out:
819         if (cn.cn_flags & HASBUF) {
820                 uma_zfree(namei_zone, cn.cn_pnbuf);
821                 cn.cn_flags &= ~HASBUF;
822         }
823
824 unionfs_mkshadowdir_abort:
825         cnp->cn_cred = credbk;
826         chgproccnt(cred->cr_ruidinfo, -1, 0);
827         crfree(cred);
828
829         return (error);
830 }
831
832 /*
833  * Create a new whiteout.
834  * 
835  * dvp should be locked on entry and will be locked on return.
836  */
837 int
838 unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp,
839                    struct thread *td, char *path)
840 {
841         int             error;
842         struct vnode   *wvp;
843         struct componentname cn;
844         struct mount   *mp;
845
846         if (path == NULL)
847                 path = cnp->cn_nameptr;
848
849         wvp = NULLVP;
850         if ((error = unionfs_relookup(dvp, &wvp, cnp, &cn, td, path, strlen(path), CREATE)))
851                 return (error);
852         if (wvp != NULLVP) {
853                 if (cn.cn_flags & HASBUF) {
854                         uma_zfree(namei_zone, cn.cn_pnbuf);
855                         cn.cn_flags &= ~HASBUF;
856                 }
857                 if (dvp == wvp)
858                         vrele(wvp);
859                 else
860                         vput(wvp);
861
862                 return (EEXIST);
863         }
864
865         if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)))
866                 goto unionfs_mkwhiteout_free_out;
867         error = VOP_WHITEOUT(dvp, &cn, CREATE);
868
869         vn_finished_write(mp);
870
871 unionfs_mkwhiteout_free_out:
872         if (cn.cn_flags & HASBUF) {
873                 uma_zfree(namei_zone, cn.cn_pnbuf);
874                 cn.cn_flags &= ~HASBUF;
875         }
876
877         return (error);
878 }
879
880 /*
881  * Create a new vnode for create a new shadow file.
882  * 
883  * If an error is returned, *vpp will be invalid, otherwise it will hold a
884  * locked, referenced and opened vnode.
885  * 
886  * unp is never updated.
887  */
888 static int
889 unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp,
890                            struct unionfs_node *unp, struct vattr *uvap,
891                            struct thread *td)
892 {
893         struct unionfs_mount *ump;
894         struct vnode   *vp;
895         struct vnode   *lvp;
896         struct ucred   *cred;
897         struct vattr    lva;
898         int             fmode;
899         int             error;
900         struct componentname cn;
901
902         ump = MOUNTTOUNIONFSMOUNT(UNIONFSTOV(unp)->v_mount);
903         vp = NULLVP;
904         lvp = unp->un_lowervp;
905         cred = td->td_ucred;
906         fmode = FFLAGS(O_WRONLY | O_CREAT | O_TRUNC | O_EXCL);
907         error = 0;
908
909         if ((error = VOP_GETATTR(lvp, &lva, cred)) != 0)
910                 return (error);
911         unionfs_create_uppervattr_core(ump, &lva, uvap, td);
912
913         if (unp->un_path == NULL)
914                 panic("unionfs: un_path is null");
915
916         cn.cn_namelen = strlen(unp->un_path);
917         cn.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK);
918         bcopy(unp->un_path, cn.cn_pnbuf, cn.cn_namelen + 1);
919         cn.cn_nameiop = CREATE;
920         cn.cn_flags = (LOCKPARENT | LOCKLEAF | HASBUF | SAVENAME | ISLASTCN);
921         cn.cn_lkflags = LK_EXCLUSIVE;
922         cn.cn_thread = td;
923         cn.cn_cred = cred;
924         cn.cn_nameptr = cn.cn_pnbuf;
925         cn.cn_consume = 0;
926
927         vref(udvp);
928         if ((error = relookup(udvp, &vp, &cn)) != 0)
929                 goto unionfs_vn_create_on_upper_free_out2;
930         vrele(udvp);
931
932         if (vp != NULLVP) {
933                 if (vp == udvp)
934                         vrele(vp);
935                 else
936                         vput(vp);
937                 error = EEXIST;
938                 goto unionfs_vn_create_on_upper_free_out1;
939         }
940
941         if ((error = VOP_CREATE(udvp, &vp, &cn, uvap)) != 0)
942                 goto unionfs_vn_create_on_upper_free_out1;
943
944         if ((error = VOP_OPEN(vp, fmode, cred, td, NULL)) != 0) {
945                 vput(vp);
946                 goto unionfs_vn_create_on_upper_free_out1;
947         }
948         VOP_ADD_WRITECOUNT(vp, 1);
949         CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d",  __func__, vp,
950             vp->v_writecount);
951         *vpp = vp;
952
953 unionfs_vn_create_on_upper_free_out1:
954         VOP_UNLOCK(udvp, LK_RELEASE);
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         VOP_ADD_WRITECOUNT(uvp, -1);
1086         CTR3(KTR_VFS, "%s: vp %p v_writecount decreased to %d", __func__, uvp,
1087             uvp->v_writecount);
1088
1089         vn_finished_write(mp);
1090
1091         if (error == 0) {
1092                 /* Reset the attributes. Ignore errors. */
1093                 uva.va_type = VNON;
1094                 VOP_SETATTR(uvp, &uva, cred);
1095         }
1096
1097         unionfs_node_update(unp, uvp, td);
1098
1099         return (error);
1100 }
1101
1102 /*
1103  * It checks whether vp can rmdir. (check empty)
1104  *
1105  * vp is unionfs vnode.
1106  * vp should be locked.
1107  */
1108 int
1109 unionfs_check_rmdir(struct vnode *vp, struct ucred *cred, struct thread *td)
1110 {
1111         int             error;
1112         int             eofflag;
1113         int             lookuperr;
1114         struct vnode   *uvp;
1115         struct vnode   *lvp;
1116         struct vnode   *tvp;
1117         struct vattr    va;
1118         struct componentname cn;
1119         /*
1120          * The size of buf needs to be larger than DIRBLKSIZ.
1121          */
1122         char            buf[256 * 6];
1123         struct dirent  *dp;
1124         struct dirent  *edp;
1125         struct uio      uio;
1126         struct iovec    iov;
1127
1128         ASSERT_VOP_ELOCKED(vp, "unionfs_check_rmdir");
1129
1130         eofflag = 0;
1131         uvp = UNIONFSVPTOUPPERVP(vp);
1132         lvp = UNIONFSVPTOLOWERVP(vp);
1133
1134         /* check opaque */
1135         if ((error = VOP_GETATTR(uvp, &va, cred)) != 0)
1136                 return (error);
1137         if (va.va_flags & OPAQUE)
1138                 return (0);
1139
1140         /* open vnode */
1141 #ifdef MAC
1142         if ((error = mac_vnode_check_open(cred, vp, VEXEC|VREAD)) != 0)
1143                 return (error);
1144 #endif
1145         if ((error = VOP_ACCESS(vp, VEXEC|VREAD, cred, td)) != 0)
1146                 return (error);
1147         if ((error = VOP_OPEN(vp, FREAD, cred, td, NULL)) != 0)
1148                 return (error);
1149
1150         uio.uio_rw = UIO_READ;
1151         uio.uio_segflg = UIO_SYSSPACE;
1152         uio.uio_td = td;
1153         uio.uio_offset = 0;
1154
1155 #ifdef MAC
1156         error = mac_vnode_check_readdir(td->td_ucred, lvp);
1157 #endif
1158         while (!error && !eofflag) {
1159                 iov.iov_base = buf;
1160                 iov.iov_len = sizeof(buf);
1161                 uio.uio_iov = &iov;
1162                 uio.uio_iovcnt = 1;
1163                 uio.uio_resid = iov.iov_len;
1164
1165                 error = VOP_READDIR(lvp, &uio, cred, &eofflag, NULL, NULL);
1166                 if (error != 0)
1167                         break;
1168                 if (eofflag == 0 && uio.uio_resid == sizeof(buf)) {
1169 #ifdef DIAGNOSTIC
1170                         panic("bad readdir response from lower FS.");
1171 #endif
1172                         break;
1173                 }
1174
1175                 edp = (struct dirent*)&buf[sizeof(buf) - uio.uio_resid];
1176                 for (dp = (struct dirent*)buf; !error && dp < edp;
1177                      dp = (struct dirent*)((caddr_t)dp + dp->d_reclen)) {
1178                         if (dp->d_type == DT_WHT || dp->d_fileno == 0 ||
1179                             (dp->d_namlen == 1 && dp->d_name[0] == '.') ||
1180                             (dp->d_namlen == 2 && !bcmp(dp->d_name, "..", 2)))
1181                                 continue;
1182
1183                         cn.cn_namelen = dp->d_namlen;
1184                         cn.cn_pnbuf = NULL;
1185                         cn.cn_nameptr = dp->d_name;
1186                         cn.cn_nameiop = LOOKUP;
1187                         cn.cn_flags = (LOCKPARENT | LOCKLEAF | SAVENAME | RDONLY | ISLASTCN);
1188                         cn.cn_lkflags = LK_EXCLUSIVE;
1189                         cn.cn_thread = td;
1190                         cn.cn_cred = cred;
1191                         cn.cn_consume = 0;
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