xref: /netbsd-src/share/man/man9/genfs_rename.9 (revision f5e669e2edc29a8cb4fd061be48101dbd02214fd)
1.\"	$NetBSD: genfs_rename.9,v 1.5 2022/01/17 22:27:10 wiz Exp $
2.\"
3.\" Copyright (c) 2013 The NetBSD Foundation, Inc.
4.\" All rights reserved.
5.\"
6.\" This documentation is derived from text contributed to The NetBSD
7.\" Foundation by Taylor R. Campbell.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21.\" PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28.\" POSSIBILITY OF SUCH DAMAGE.
29.\"
30.Dd May 1, 2013
31.Dt GENFS_RENAME 9
32.Os
33.Sh NAME
34.Nm genfs_rename ,
35.Nm genfs_insane_rename ,
36.Nm genfs_sane_rename
37.Nd generic framework for implementing
38.Xr VOP_RENAME 9
39.Sh SYNOPSIS
40.Ft int
41.Fo genfs_insane_rename
42.Fa "struct vop_rename_args *v"
43.Fa "int (*sane_rename)(struct vnode *fdvp, struct componentname *fcnp, struct vnode *tdvp, struct componentname *tcnp, kauth_cred_t, bool)"
44.Fc
45.Ft int
46.Fo genfs_sane_rename
47.Fa "const struct genfs_rename_ops *gro"
48.Fa "struct vnode *fdvp"
49.Fa "struct componentname *fcnp"
50.Fa "void *fde"
51.Fa "struct vnode *tdvp"
52.Fa "struct componentname *tcnp"
53.Fa "void *tde"
54.Fa "kauth_cred_t cred"
55.Fa "bool posixly_correct"
56.Fc
57.Ft int
58.Fo genfs_rename_knote
59.Fa "struct vnode *fdvp"
60.Fa "struct vnode *fvp"
61.Fa "struct vnode *tdvp"
62.Fa "struct vnode *tvp"
63.Fc
64.Ft void
65.Fo genfs_rename_cache_purge
66.Fa "struct vnode *fdvp"
67.Fa "struct vnode *fvp"
68.Fa "struct vnode *tdvp"
69.Fa "struct vnode *tvp"
70.Fc
71.Ft int
72.Fo genfs_ufslike_rename_check_possible
73.Fa "unsigned long fdflags"
74.Fa "unsigned long fflags"
75.Fa "unsigned long tdflags"
76.Fa "unsigned long tflags"
77.Fa "bool clobber"
78.Fa "unsigned long immutable"
79.Fa "unsigned long append"
80.Fc
81.Ft int
82.Fo genfs_ufslike_rename_check_permitted
83.Fa "kauth_cred_t cred"
84.Fa "struct vnode *fdvp"
85.Fa "mode_t fdmode"
86.Fa "uid_t fduid"
87.Fa "struct vnode *fvp"
88.Fa "uid_t fuid"
89.Fa "struct vnode *tdvp"
90.Fa "mode_t tdmode"
91.Fa "uid_t tduid"
92.Fa "struct vnode *tvp"
93.Fa "uid_t tuid"
94.Fc
95.Ft int
96.Fo genfs_ufslike_remove_check_possible
97.Fa "unsigned long dflags"
98.Fa "unsigned long flags"
99.Fa "unsigned long immutable"
100.Fa "unsigned long append"
101.Fc
102.Ft int
103.Fo genfs_ufslike_remove_check_permitted
104.Fa "kauth_cred_t cred"
105.Fa "struct vnode *dvp"
106.Fa "mode_t dmode"
107.Fa "uid_t duid"
108.Fa "struct vnode *vp"
109.Fa "uid_t uid"
110.Fc
111.Sh DESCRIPTION
112The
113.Nm
114functions provide a file-system-independent framework for implementing
115.Xr VOP_RENAME 9
116with correct locking and error-checking.
117.Pp
118Implementing rename is nontrivial.
119If you are doing it for a new file system, you should consider starting
120from
121.Fn tmpfs_rename
122as implemented in
123.Pa sys/fs/tmpfs/tmpfs_rename.c
124and adapting it to your file system's physical operations.
125.Pp
126Because there are so many moving parts to a rename operation,
127.Nm
128uses the following naming conventions:
129.Bl -tag -width indent
130.It Fa mp Pq "mount point"
131mount point of the file system in question
132.It Fa fdvp Pq "from directory vnode pointer"
133directory from which we are removing an entry
134.It Fa fcnp Pq "from componentname pointer"
135name of entry to remove from
136.Fa fdvp
137.It Fa fde Pq "from directory entry"
138fs-specific data about the entry in
139.Fa fdvp
140.It Fa fvp Pq "from vnode pointer"
141file at the entry named
142.Fa fcnp
143in
144.Fa fdvp
145.It Fa tdvp Pq "to directory vnode pointer"
146directory to which we are adding an entry
147.It Fa tcnp Pq "to componentname pointer"
148name of entry to add to
149.Fa tdvp
150.It Fa tde Pq "to directory entry"
151fs-specific data about the entry in
152.Fa tdvp
153.It Fa tvp Pq "to vnode pointer"
154file previously at the entry named
155.Fa tcnp
156in
157.Fa tdvp ,
158to be replaced, if any, or
159.Dv NULL
160if there was no entry before
161.It Fa vp Pq "vnode pointer"
162any file
163.It Fa dvp Pq "directory vnode pointer"
164any directory with an entry for
165.Fa vp
166.El
167.Pp
168A file system mumblefs should implement various file-system-dependent
169parts of the rename operation in a
170.Vt struct genfs_rename_ops ,
171and use
172.Nm
173to implement
174.Fn mumblefs_rename
175for
176.Xr VOP_RENAME 9
177as follows:
178.Bd -literal -offset indent
179static const struct genfs_rename_ops mumblefs_genfs_rename_ops;
180
181static int
182mumblefs_sane_rename(
183    struct vnode *fdvp, struct componentname *fcnp,
184    struct vnode *tdvp, struct componentname *tcnp,
185    kauth_cred_t cred, bool posixly_correct)
186{
187	struct mumblefs_lookup_results fulr, tulr;
188
189	return genfs_sane_rename(&mumblefs_genfs_rename_ops,
190	    fdvp, fcnp, &fulr, tdvp, tcnp, &tulr,
191	    cred, posixly_correct);
192}
193
194int
195mumblefs_rename(void *v)
196{
197
198	return genfs_insane_rename(v, &mumblefs_sane_rename);
199}
200.Ed
201.Pp
202The split between
203.Fn mumblefs_rename
204and
205.Fn mumblefs_sane_rename
206is designed to enable us to easily change the
207.Xr VOP_RENAME 9
208interface, which is currently designed for a broken (hence
209.Sq insane )
210locking scheme, to a more sensible locking scheme once all the file
211systems have their rename operations split up thus.
212.Pp
213The
214.Vt struct mumblefs_lookup_results
215structure is storage for information about directory entries which
216needs to pass from the lookups of the children (see the
217.Fa gro_lookup
218member of
219.Vt "struct genfs_rename_ops" )
220to the physical on-disk rename or remove operations (see the
221.Fa gro_rename
222and
223.Fa gro_remove
224members of
225.Vt "struct genfs_rename_ops" ) .
226.Pp
227Callers must implement the following operations as members in a
228.Vt struct genfs_rename_ops
229structure passed to
230.Nm :
231.Bl -tag -width indent
232.It Ft int Fn "(*gro_genealogy)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *fdvp" "struct vnode *tdvp" "struct vnode **intermediate_node_ret"
233Walk up the directory tree from the directory vnode
234.Fa tdvp
235until hitting either
236.Fa fdvp
237or the root.
238If
239.Fa fdvp
240is hit, store the child of
241.Fa fdvp
242through which the path from
243.Fa tdvp
244passed in
245.Fa *intermediate_node_ret ,
246referenced but unlocked.
247If
248.Fa fdvp
249is not hit, store
250.Dv NULL
251in
252.Fa *intermediate_node_ret .
253Return zero on success or error on failure.
254(Failure means file-system-specific failures, not hitting or missing
255.Fa fdvp . )
256.Pp
257.Fa fdvp
258and
259.Fa tdvp
260are guaranteed to be distinct, non-null, referenced, and unlocked.
261Since no locks are held on entry except for the file-system-wide rename
262lock,
263.Fa gro_genealogy
264may take any locks it pleases.
265.It Ft int Fn "(*gro_lock_directory)" "struct mount *mp" "struct vnode *vp"
266Lock the directory vnode
267.Fa vp ,
268but fail if it has been rmdired already.
269Return zero on success or error on failure.
270.It Ft int Fn "(*gro_lookup)" "struct mount *mp" "struct vnode *dvp" "struct componentname *cnp" "void *de" "struct vnode **vpp"
271Look up the entry in
272.Fa dvp
273for
274.Fa cnp ,
275storing the vnode in
276.Fa "*vpp"
277and using
278.Fa de ,
279one of the pointers passed to
280.Nm genfs_sane_rename ,
281to store information about the directory entry as needed by the file
282system's
283.Fa gro_rename
284operation, and return zero.
285If there is no such entry, return error.
286.Pp
287.Fa dvp
288is guaranteed to be locked, and the vnode returned in
289.Fa "*vpp"
290must be unlocked.
291However,
292.Fa gro_lookup
293may temporarily lock the vnode without causing deadlock.
294.It Ft bool Fn "(*gro_directory_empty_p)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *vp" "struct vnode *dvp"
295Return true if the directory vnode
296.Fa vp
297is empty.
298The argument
299.Fa dvp
300is the parent of
301.Fa vp ,
302as required for this check by some file systems.
303.Pp
304.Fa dvp
305and
306.Fa vp
307are guaranteed to be distinct, non-null, referenced, and locked.
308.It Ft int Fn "(*gro_rename_check_possible)" "struct mount *mp" "struct vnode *fdvp" "struct vnode *fvp" "struct vnode *tdvp" "struct vnode *tvp"
309Return zero if the file system might allow the rename independent of
310credentials, or error if not.
311This should check, for example, any immutability flags in the vnodes in
312question, and should use
313.Fn genfs_ufslike_rename_check_possible
314for file systems similar to UFS/FFS.
315.Pp
316.Fa fdvp
317and
318.Fa tdvp
319may be the same; every other pair of vnodes is guaranteed to be
320distinct.
321.Fa tvp
322may be
323.Dv NULL ;
324every other vnode is guaranteed to be non-null.
325All three or four vnodes are guaranteed to be referenced and locked.
326.It Ft int Fn "(*gro_rename_check_permitted)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *fdvp" "struct vnode *fvp" "struct vnode *tdvp" "struct vnode *tvp"
327Return zero if the file system allows the rename given the credentials
328.Fa cred ,
329or error if not.
330This should check, for example, the ownership and permissions bits of
331the vnodes in question, and should use
332.Fn genfs_ufslike_rename_check_permitted
333for file systems similar to UFS/FFS.
334.Pp
335.Fa fdvp
336and
337.Fa tdvp
338may be the same; every other pair of vnodes is guaranteed to be
339distinct.
340.Fa tvp
341may be
342.Dv NULL ;
343every other vnode is guaranteed to be non-null.
344All three or four vnodes are guaranteed to be referenced and locked.
345.It Ft int Fn "(*gro_rename)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *fdvp" "struct componentname *fcnp" "void *fde" "struct vnode *fvp" "struct vnode *tdvp" "struct componentname *tcnp" "void *tde" "struct vnode *tvp"
346Perform the physical file system rename operation, report any knotes,
347and purge the namecache entries.
348Return zero on success or error on failure.
349All file-system-independent error cases have been handled already.
350.Pp
351File systems using
352.Xr fstrans 9
353should use
354.Xr fstrans_start 9
355and
356.Xr fstrans_done 9
357here.
358.Fa fde
359and
360.Fa tde
361are the pointers that were supplied to
362.Fn genfs_sane_rename
363and got passed to the
364.Fa gro_lookup
365operation to find information about directory entries.
366.Pp
367This may use
368.Fn genfs_rename_knote
369to report any knotes, if the various file-system-dependent routines it
370uses to edit links don't do that already.
371This should use
372.Fn genfs_rename_cache_purge
373to purge the namecache.
374.Pp
375.Fa fdvp
376and
377.Fa tdvp
378may be the same; every other pair of vnodes is guaranteed to be
379distinct.
380.Fa tvp
381may be null; every other vnode is guaranteed to be non-null.
382All three or four vnodes are guaranteed to be referenced and locked.
383.It Ft int Fn "(*gro_remove_check_possible)" "struct mount *mp" "struct vnode *dvp" "struct vnode *vp"
384Return zero if the file system might allow removing an entry in
385.Fa dvp
386for
387.Fa vp
388independent of credentials, or error if not.
389This should use
390.Fn genfs_ufslike_remove_check_possible
391for file systems similar to UFS/FFS.
392.Pp
393.Fa dvp
394and
395.Fa vp
396are guaranteed to be distinct, non-null, referenced, and locked.
397.Pp
398This, and
399.Fa gro_remove_check_permitted
400below, are for renames that reduce to a remove; that is, renaming one
401entry to another when both entries refer to the same file.
402For reasons of locking insanity,
403.Nm
404cannot simply call
405.Xr VOP_REMOVE 9
406instead.
407.It Ft int Fn "(*gro_remove_check_permitted)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *dvp" "struct vnode *vp"
408Return zero if the file system allows removing an entry in
409.Fa dvp
410for
411.Fa vp
412given the credentials
413.Fa cred ,
414or error if not.
415This should use
416.Fn genfs_ufslike_remove_check_permitted
417for file systems similar to UFS/FFS.
418.Pp
419.Fa dvp
420and
421.Fa vp
422are guaranteed to be distinct, non-null, referenced, and locked.
423.It Ft int Fn "(*gro_remove)" "struct mount *mp" "kauth_cred_t cred" "struct vnode *dvp" "struct componentname *cnp" "void *de" "struct vnode *vp"
424For a rename that is effectively a remove, perform the physical file
425system remove operation, report any knotes, and purge the namecache
426entries.
427Return zero on success or error on failure.
428All file-system-independent error cases have been handled already.
429.Pp
430File systems using
431.Xr fstrans 9
432should use
433.Xr fstrans_start 9
434and
435.Xr fstrans_done 9
436here.
437.Fa de
438is one of the pointers that were supplied to
439.Fn genfs_sane_rename
440and got passed to the
441.Fa gro_lookup
442operation to find information about directory entries.
443.Pp
444This should signal a
445.Dv NOTE_WRITE
446knote for
447.Fa dvp ,
448and either a
449.Dv NOTE_DELETE
450or a
451.Dv NOTE_LINK
452knote for
453.Fa vp ,
454depending on whether this removed the last link to it or not.
455.Pp
456.Fa dvp
457and
458.Fa vp
459are guaranteed to be distinct, non-null, referenced, and locked.
460.El
461.Pp
462The following utilities are provided for implementing the
463.Vt struct genfs_rename_ops
464operations:
465.Bl -tag -width indent
466.It Fn genfs_rename_knote fdvp fvp tdvp tvp
467Signal all the knotes relevant for the rename operation.
468.It Fn genfs_rename_cache_purge fdvp fvp tdvp tvp
469Purge any namecache entries that the rename operation invalidates.
470.It Fn genfs_ufslike_rename_check_possible fdflags fflags tdflags tflags clobber immutable append
471Check whether the UFS/FFS-like flags of the files involved a rename
472allow it.
473Return zero if allowed or error if not.
474.Pp
475.Bl -tag -width immutable -compact
476.It Fa fdflags
477flags of source directory
478.It Fa fflags
479flags of source file
480.It Fa tdflags
481flags of target directory
482.It Fa tflags
483flags of target file, if there is one and
484.Fa clobber
485is true, or ignored otherwise
486.It Fa clobber
487true if there is a target file whose entry will be clobbered or false
488if not
489.It Fa immutable
490bit mask for the file system's immutable bit, like the UFS/FFS
491.Dv IMMUTABLE
492.It Fa append
493bit mask for the file system's append-only bit, like the UFS/FFS
494.Dv APPEND
495.El
496.It Fn genfs_ufslike_rename_check_permitted cred fdvp fdmode fduid fvp fuid tdvp tdmode tduid tvp tuid
497Check whether the credentials
498.Fa cred
499are permitted by the file ownership and permissions bits to perform a
500rename.
501Return zero if permitted or error if not.
502.Pp
503.Bl -tag -width fdmode -compact
504.It Fa cred
505caller's credentials
506.It Fa fdvp
507source directory
508.It Fa fdmode
509file permissions bits of
510.Fa fdvp
511.It Fa fduid
512uid of the owner of
513.Fa fdvp
514.It Fa fvp
515source file
516.It Fa fuid
517uid of owner of
518.Fa fvp
519.It Fa tdvp
520target directory
521.It Fa tdmode
522file permissions bits of
523.Fa tdvp
524.It Fa tduid
525uid of owner of
526.Fa tdvp
527.It Fa tvp
528target file, if there is one, or
529.Dv NULL
530if not
531.It Fa tuid
532uid of owner of
533.Fa tvp ,
534if there is a target file, or ignored otherwise
535.El
536.It Fn genfs_ufslike_remove_check_possible dflags flags immutable append
537Check whether the UFS/FFS-like flags of the files involved a remove
538allow it.
539Return zero if allowed or error if not.
540.Pp
541.Bl -tag -width immutable -compact
542.It Fa dflags
543flags of the directory
544.It Fa flags
545flags of the file in the directory
546.It Fa immutable
547bit mask for the file system's immutable bit, like the UFS/FFS
548.Dv IMMUTABLE
549.It Fa append
550bit mask for the file system's append-only bit, like the UFS/FFS
551.Dv APPEND
552.El
553.It Fn genfs_ufslike_remove_check_permitted cred dvp dmode duid vp uid
554Check whether the credentials
555.Fa cred
556are permitted by the file ownership and permissions bits to perform a
557remove.
558Return zero if permitted or error if not.
559.Pp
560.Bl -tag -width fdmode -compact
561.It Fa cred
562caller's credentials
563.It Fa dvp
564directory
565.It Fa dmode
566file permissions bits of
567.Fa dvp
568.It Fa duid
569uid of owner of
570.Fa dvp
571.It Fa vp
572file in
573.Fa dvp
574.It Fa uid
575uid of owner of
576.Fa vp
577.El
578.El
579.Sh NOTES
580Because there are so many cases of rename, it cannot be assumed a
581priori that any pairs of
582.Fa fdvp ,
583.Fa fvp ,
584.Fa tdvp ,
585or
586.Fa fvp
587are distinct:
588.Bl -column -offset indent \
589"fdvp = tdvp" "rename(\*qa/b\*q, \*qa/c\*q)"
590.It Li "fdvp = fvp"     Ta Li "rename(\*qa/.\*q, \*qb\*q)"
591.It Li "fdvp = tdvp"    Ta Li "rename(\*qa/b\*q, \*qa/c\*q)"
592.It Li "fdvp = tvp"     Ta Li "rename(\*qa/b\*q, \*qa\*q)"
593.It Li "fvp = tdvp"     Ta Li "rename(\*qa\*q, \*qa/b\*q)"
594.It Li "fvp = tvp"      Ta Li "rename(\*qa\*q, \*qa\*q)"
595.It Li "tdvp = tvp"     Ta Li "rename(\*qa\*q, \*qb/.\*q)"
596.El
597.Pp
598Handling all these cases correctly, and getting the locking correct and
599deadlock-free, is very tricky, which is why
600.Nm
601exists.
602The interface to
603.Nm
604is very complicated because it must fit the insane
605.Xr VOP_RENAME 9
606and
607.Xr VOP_LOOKUP 9
608protocols until we can fix them, and because it must accommodate a
609variety of crufty file systems.
610.Sh SEE ALSO
611.Xr genfs 9 ,
612.Xr vfs 9 ,
613.Xr vnodeops 9
614.Sh HISTORY
615.Nm
616was designed and implemented by
617.An Taylor R. Campbell Aq Mt riastradh@NetBSD.org
618after many discussions with
619.An David Holland Aq Mt dholland@NetBSD.org ,
620and first appeared in
621.Nx 6.0 .
622