Deleted Added
full compact
ext2_vnops.c (198940) ext2_vnops.c (202283)
1/*-
2 * modified for EXT2FS support in Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*-
8 * Copyright (c) 1982, 1986, 1989, 1993

--- 25 unchanged lines hidden (view full) ---

34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)ufs_vnops.c 8.7 (Berkeley) 2/3/94
41 * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
1/*-
2 * modified for EXT2FS support in Lites 1.1
3 *
4 * Aug 1995, Godmar Back (gback@cs.utah.edu)
5 * University of Utah, Department of Computer Science
6 */
7/*-
8 * Copyright (c) 1982, 1986, 1989, 1993

--- 25 unchanged lines hidden (view full) ---

34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)ufs_vnops.c 8.7 (Berkeley) 2/3/94
41 * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95
42 * $FreeBSD: head/sys/gnu/fs/ext2fs/ext2_vnops.c 198940 2009-11-05 04:51:38Z jh $
42 * $FreeBSD: head/sys/fs/ext2fs/ext2_vnops.c 202283 2010-01-14 14:30:54Z lulf $
43 */
44
45#include "opt_suiddir.h"
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/resourcevar.h>
50#include <sys/kernel.h>

--- 18 unchanged lines hidden (view full) ---

69#include <vm/vm_extern.h>
70#include <vm/vnode_pager.h>
71
72#include <fs/fifofs/fifo.h>
73
74#include <sys/signalvar.h>
75#include <ufs/ufs/dir.h>
76
43 */
44
45#include "opt_suiddir.h"
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/resourcevar.h>
50#include <sys/kernel.h>

--- 18 unchanged lines hidden (view full) ---

69#include <vm/vm_extern.h>
70#include <vm/vnode_pager.h>
71
72#include <fs/fifofs/fifo.h>
73
74#include <sys/signalvar.h>
75#include <ufs/ufs/dir.h>
76
77#include <gnu/fs/ext2fs/inode.h>
78#include <gnu/fs/ext2fs/ext2_mount.h>
79#include <gnu/fs/ext2fs/ext2_fs_sb.h>
80#include <gnu/fs/ext2fs/fs.h>
81#include <gnu/fs/ext2fs/ext2_extern.h>
82#include <gnu/fs/ext2fs/ext2_fs.h>
77#include
78#include
79#include <fs/ext2fs/fs.h>
80#include <fs/ext2fs/ext2_extern.h>
81#include <fs/ext2fs/ext2fs.h>
82#include <fs/ext2fs/ext2_dir.h>
83
84static int ext2_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
83
84static int ext2_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *);
85static void ext2_itimes_locked(struct vnode *);
85
86static vop_access_t ext2_access;
87static int ext2_chmod(struct vnode *, int, struct ucred *, struct thread *);
88static int ext2_chown(struct vnode *, uid_t, gid_t, struct ucred *,
89 struct thread *);
90static vop_close_t ext2_close;
91static vop_create_t ext2_create;
92static vop_fsync_t ext2_fsync;

--- 62 unchanged lines hidden (view full) ---

155 .vop_print = ext2_print,
156 .vop_read = VOP_PANIC,
157 .vop_reclaim = ext2_reclaim,
158 .vop_setattr = ext2_setattr,
159 .vop_write = VOP_PANIC,
160 .vop_vptofh = ext2_vptofh,
161};
162
86
87static vop_access_t ext2_access;
88static int ext2_chmod(struct vnode *, int, struct ucred *, struct thread *);
89static int ext2_chown(struct vnode *, uid_t, gid_t, struct ucred *,
90 struct thread *);
91static vop_close_t ext2_close;
92static vop_create_t ext2_create;
93static vop_fsync_t ext2_fsync;

--- 62 unchanged lines hidden (view full) ---

156 .vop_print = ext2_print,
157 .vop_read = VOP_PANIC,
158 .vop_reclaim = ext2_reclaim,
159 .vop_setattr = ext2_setattr,
160 .vop_write = VOP_PANIC,
161 .vop_vptofh = ext2_vptofh,
162};
163
163#include <gnu/fs/ext2fs/ext2_readwrite.c>
164#include
164
165/*
166 * A virgin directory (no blushing please).
167 * Note that the type and namlen fields are reversed relative to ext2.
168 * Also, we don't use `struct odirtemplate', since it would just cause
169 * endianness problems.
170 */
171static struct dirtemplate mastertemplate = {
172 0, 12, 1, EXT2_FT_DIR, ".",
173 0, DIRBLKSIZ - 12, 2, EXT2_FT_DIR, ".."
174};
175static struct dirtemplate omastertemplate = {
176 0, 12, 1, EXT2_FT_UNKNOWN, ".",
177 0, DIRBLKSIZ - 12, 2, EXT2_FT_UNKNOWN, ".."
178};
179
165
166/*
167 * A virgin directory (no blushing please).
168 * Note that the type and namlen fields are reversed relative to ext2.
169 * Also, we don't use `struct odirtemplate', since it would just cause
170 * endianness problems.
171 */
172static struct dirtemplate mastertemplate = {
173 0, 12, 1, EXT2_FT_DIR, ".",
174 0, DIRBLKSIZ - 12, 2, EXT2_FT_DIR, ".."
175};
176static struct dirtemplate omastertemplate = {
177 0, 12, 1, EXT2_FT_UNKNOWN, ".",
178 0, DIRBLKSIZ - 12, 2, EXT2_FT_UNKNOWN, ".."
179};
180
180void
181ext2_itimes(vp)
182 struct vnode *vp;
181static void
182ext2_itimes_locked(struct vnode *vp)
183{
184 struct inode *ip;
185 struct timespec ts;
186
183{
184 struct inode *ip;
185 struct timespec ts;
186
187 ASSERT_VI_LOCKED(vp, __func__);
188
187 ip = VTOI(vp);
188 if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
189 return;
190 if ((vp->v_type == VBLK || vp->v_type == VCHR))
191 ip->i_flag |= IN_LAZYMOD;
192 else
193 ip->i_flag |= IN_MODIFIED;
194 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {

--- 10 unchanged lines hidden (view full) ---

205 if (ip->i_flag & IN_CHANGE) {
206 ip->i_ctime = ts.tv_sec;
207 ip->i_ctimensec = ts.tv_nsec;
208 }
209 }
210 ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
211}
212
189 ip = VTOI(vp);
190 if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0)
191 return;
192 if ((vp->v_type == VBLK || vp->v_type == VCHR))
193 ip->i_flag |= IN_LAZYMOD;
194 else
195 ip->i_flag |= IN_MODIFIED;
196 if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {

--- 10 unchanged lines hidden (view full) ---

207 if (ip->i_flag & IN_CHANGE) {
208 ip->i_ctime = ts.tv_sec;
209 ip->i_ctimensec = ts.tv_nsec;
210 }
211 }
212 ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE);
213}
214
215void
216ext2_itimes(struct vnode *vp)
217{
218
219 VI_LOCK(vp);
220 ext2_itimes_locked(vp);
221 VI_UNLOCK(vp);
222}
223
213/*
214 * Create a regular file
215 */
216static int
217ext2_create(ap)
218 struct vop_create_args /* {
219 struct vnode *a_dvp;
220 struct vnode **a_vpp;

--- 49 unchanged lines hidden (view full) ---

270 struct ucred *a_cred;
271 struct thread *a_td;
272 } */ *ap;
273{
274 struct vnode *vp = ap->a_vp;
275
276 VI_LOCK(vp);
277 if (vp->v_usecount > 1)
224/*
225 * Create a regular file
226 */
227static int
228ext2_create(ap)
229 struct vop_create_args /* {
230 struct vnode *a_dvp;
231 struct vnode **a_vpp;

--- 49 unchanged lines hidden (view full) ---

281 struct ucred *a_cred;
282 struct thread *a_td;
283 } */ *ap;
284{
285 struct vnode *vp = ap->a_vp;
286
287 VI_LOCK(vp);
288 if (vp->v_usecount > 1)
278 ext2_itimes(vp);
289 ext2_itimes_locked(vp);
279 VI_UNLOCK(vp);
280 return (0);
281}
282
283static int
284ext2_access(ap)
285 struct vop_access_args /* {
286 struct vnode *a_vp;

--- 24 unchanged lines hidden (view full) ---

311 return (EROFS);
312 break;
313 default:
314 break;
315 }
316 }
317
318 /* If immutable bit set, nobody gets to write it. */
290 VI_UNLOCK(vp);
291 return (0);
292}
293
294static int
295ext2_access(ap)
296 struct vop_access_args /* {
297 struct vnode *a_vp;

--- 24 unchanged lines hidden (view full) ---

322 return (EROFS);
323 break;
324 default:
325 break;
326 }
327 }
328
329 /* If immutable bit set, nobody gets to write it. */
319 if ((accmode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT)))
330 if ((accmode & VWRITE) && (ip->i_flags & (SF_IMMUTABLE | SF_SNAPSHOT)))
320 return (EPERM);
321
322 error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
323 ap->a_accmode, ap->a_cred, NULL);
324 return (error);
325}
326
327static int

--- 58 unchanged lines hidden (view full) ---

386 */
387 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
388 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
389 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
390 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
391 return (EINVAL);
392 }
393 if (vap->va_flags != VNOVAL) {
331 return (EPERM);
332
333 error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid,
334 ap->a_accmode, ap->a_cred, NULL);
335 return (error);
336}
337
338static int

--- 58 unchanged lines hidden (view full) ---

397 */
398 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
399 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
400 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
401 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
402 return (EINVAL);
403 }
404 if (vap->va_flags != VNOVAL) {
394 /* Disallow flags not supported by ext2fs. */
395 if (vap->va_flags & ~(SF_APPEND | SF_IMMUTABLE | UF_NODUMP))
396 return (EOPNOTSUPP);
397
398 if (vp->v_mount->mnt_flag & MNT_RDONLY)
399 return (EROFS);
405 if (vp->v_mount->mnt_flag & MNT_RDONLY)
406 return (EROFS);
407 /* Disallow flags not supported by ext2fs. */
408 if(vap->va_flags & ~(SF_APPEND | SF_IMMUTABLE | UF_NODUMP))
409 return(EOPNOTSUPP);
400 /*
401 * Callers may only modify the file flags on objects they
402 * have VADMIN rights for.
403 */
404 if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
405 return (error);
406 /*
407 * Unprivileged processes and privileged processes in

--- 7 unchanged lines hidden (view full) ---

415 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
416 error = securelevel_gt(cred, 0);
417 if (error)
418 return (error);
419 }
420 ip->i_flags = vap->va_flags;
421 } else {
422 if (ip->i_flags
410 /*
411 * Callers may only modify the file flags on objects they
412 * have VADMIN rights for.
413 */
414 if ((error = VOP_ACCESS(vp, VADMIN, cred, td)))
415 return (error);
416 /*
417 * Unprivileged processes and privileged processes in

--- 7 unchanged lines hidden (view full) ---

425 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
426 error = securelevel_gt(cred, 0);
427 if (error)
428 return (error);
429 }
430 ip->i_flags = vap->va_flags;
431 } else {
432 if (ip->i_flags
423 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) ||
424 (vap->va_flags & UF_SETTABLE) != vap->va_flags)
433 & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND))
425 return (EPERM);
426 ip->i_flags &= SF_SETTABLE;
434 return (EPERM);
435 ip->i_flags &= SF_SETTABLE;
427 ip->i_flags |= (vap->va_flags & UF_SETTABLE);
428 }
429 ip->i_flag |= IN_CHANGE;
430 if (vap->va_flags & (IMMUTABLE | APPEND))
431 return (0);
432 }
433 if (ip->i_flags & (IMMUTABLE | APPEND))
434 return (EPERM);
435 /*

--- 169 unchanged lines hidden (view full) ---

605 struct ucred *a_cred;
606 int a_waitfor;
607 struct thread *a_td;
608 } */ *ap;
609{
610 /*
611 * Flush all dirty buffers associated with a vnode.
612 */
436 }
437 ip->i_flag |= IN_CHANGE;
438 if (vap->va_flags & (IMMUTABLE | APPEND))
439 return (0);
440 }
441 if (ip->i_flags & (IMMUTABLE | APPEND))
442 return (EPERM);
443 /*

--- 169 unchanged lines hidden (view full) ---

613 struct ucred *a_cred;
614 int a_waitfor;
615 struct thread *a_td;
616 } */ *ap;
617{
618 /*
619 * Flush all dirty buffers associated with a vnode.
620 */
613 ext2_discard_prealloc(VTOI(ap->a_vp));
614
615 vop_stdfsync(ap);
616
617 return (ext2_update(ap->a_vp, ap->a_waitfor == MNT_WAIT));
618}
619
620/*
621 * Mknod vnode call

--- 116 unchanged lines hidden (view full) ---

738 ip->i_flag |= IN_CHANGE;
739 }
740out:
741 return (error);
742}
743
744/*
745 * Rename system call.
621
622 vop_stdfsync(ap);
623
624 return (ext2_update(ap->a_vp, ap->a_waitfor == MNT_WAIT));
625}
626
627/*
628 * Mknod vnode call

--- 116 unchanged lines hidden (view full) ---

745 ip->i_flag |= IN_CHANGE;
746 }
747out:
748 return (error);
749}
750
751/*
752 * Rename system call.
746 * See comments in sys/ufs/ufs/ufs_vnops.c
753 * rename("foo", "bar");
754 * is essentially
755 * unlink("bar");
756 * link("foo", "bar");
757 * unlink("foo");
758 * but ``atomically''. Can't do full commit without saving state in the
759 * inode on disk which isn't feasible at this time. Best we can do is
760 * always guarantee the target exists.
761 *
762 * Basic algorithm is:
763 *
764 * 1) Bump link count on source while we're linking it to the
765 * target. This also ensure the inode won't be deleted out
766 * from underneath us while we work (it may be truncated by
767 * a concurrent `trunc' or `open' for creation).
768 * 2) Link source to destination. If destination already exists,
769 * delete it first.
770 * 3) Unlink source reference to inode if still around. If a
771 * directory was moved and the parent of the destination
772 * is different from the source, patch the ".." entry in the
773 * directory.
747 */
748static int
749ext2_rename(ap)
750 struct vop_rename_args /* {
751 struct vnode *a_fdvp;
752 struct vnode *a_fvp;
753 struct componentname *a_fcnp;
754 struct vnode *a_tdvp;

--- 429 unchanged lines hidden (view full) ---

1184 dp->i_nlink++;
1185 dp->i_flag |= IN_CHANGE;
1186 error = ext2_update(dvp, 1);
1187 if (error)
1188 goto bad;
1189
1190 /* Initialize directory with "." and ".." from static template. */
1191 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs,
774 */
775static int
776ext2_rename(ap)
777 struct vop_rename_args /* {
778 struct vnode *a_fdvp;
779 struct vnode *a_fvp;
780 struct componentname *a_fcnp;
781 struct vnode *a_tdvp;

--- 429 unchanged lines hidden (view full) ---

1211 dp->i_nlink++;
1212 dp->i_flag |= IN_CHANGE;
1213 error = ext2_update(dvp, 1);
1214 if (error)
1215 goto bad;
1216
1217 /* Initialize directory with "." and ".." from static template. */
1218 if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs,
1192 EXT2_FEATURE_INCOMPAT_FILETYPE))
1219 EXT2F_INCOMPAT_FTYPE))
1193 dtp = &mastertemplate;
1194 else
1195 dtp = &omastertemplate;
1196 dirtemplate = *dtp;
1197 dirtemplate.dot_ino = ip->i_number;
1198 dirtemplate.dotdot_ino = dp->i_number;
1199 /* note that in ext2 DIRBLKSIZ == blocksize, not DEV_BSIZE
1200 * so let's just redefine it - for this function only
1201 */
1202#undef DIRBLKSIZ
1220 dtp = &mastertemplate;
1221 else
1222 dtp = &omastertemplate;
1223 dirtemplate = *dtp;
1224 dirtemplate.dot_ino = ip->i_number;
1225 dirtemplate.dotdot_ino = dp->i_number;
1226 /* note that in ext2 DIRBLKSIZ == blocksize, not DEV_BSIZE
1227 * so let's just redefine it - for this function only
1228 */
1229#undef DIRBLKSIZ
1203#define DIRBLKSIZ VTOI(dvp)->i_e2fs->s_blocksize
1230#define DIRBLKSIZ VTOI(dvp)->i_e2fs->e2fs_bsize
1204 dirtemplate.dotdot_reclen = DIRBLKSIZ - 12;
1205 error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
1206 sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
1207 IO_NODELOCKED | IO_SYNC | IO_NOMACCHECK, cnp->cn_cred, NOCRED,
1208 NULL, NULL);
1209 if (error) {
1210 dp->i_nlink--;
1211 dp->i_flag |= IN_CHANGE;

--- 237 unchanged lines hidden (view full) ---

1449 struct ucred *a_cred;
1450 struct thread *a_td;
1451 } */ *ap;
1452{
1453 struct vnode *vp = ap->a_vp;
1454
1455 VI_LOCK(vp);
1456 if (vp->v_usecount > 1)
1231 dirtemplate.dotdot_reclen = DIRBLKSIZ - 12;
1232 error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate,
1233 sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE,
1234 IO_NODELOCKED | IO_SYNC | IO_NOMACCHECK, cnp->cn_cred, NOCRED,
1235 NULL, NULL);
1236 if (error) {
1237 dp->i_nlink--;
1238 dp->i_flag |= IN_CHANGE;

--- 237 unchanged lines hidden (view full) ---

1476 struct ucred *a_cred;
1477 struct thread *a_td;
1478 } */ *ap;
1479{
1480 struct vnode *vp = ap->a_vp;
1481
1482 VI_LOCK(vp);
1483 if (vp->v_usecount > 1)
1457 ext2_itimes(vp);
1484 ext2_itimes_locked(vp);
1458 VI_UNLOCK(vp);
1459 return (fifo_specops.vop_close(ap));
1460}
1461
1462/*
1463 * Kqfilter wrapper for fifos.
1464 *
1465 * Fall through to ext2 kqfilter routines if needed

--- 184 unchanged lines hidden ---
1485 VI_UNLOCK(vp);
1486 return (fifo_specops.vop_close(ap));
1487}
1488
1489/*
1490 * Kqfilter wrapper for fifos.
1491 *
1492 * Fall through to ext2 kqfilter routines if needed

--- 184 unchanged lines hidden ---