version 1.63.2.6, 2007/12/07 17:35:24 |
version 1.98.4.2, 2008/12/13 01:15:41 |
Line 41 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 41 __KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
#ifdef _KERNEL_OPT |
#ifdef _KERNEL_OPT |
#include "opt_ffs.h" |
#include "opt_ffs.h" |
|
#include "fs_ffs.h" |
#endif |
#endif |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
Line 53 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 54 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/vnode.h> |
#include <sys/vnode.h> |
#include <sys/kernel.h> |
#include <sys/kernel.h> |
#include <sys/kauth.h> |
#include <sys/kauth.h> |
|
#include <sys/wapbl.h> |
#include <sys/fstrans.h> |
#include <sys/fstrans.h> |
#include <sys/proc.h> |
#include <sys/proc.h> |
#include <sys/kmem.h> |
#include <sys/kmem.h> |
Line 65 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 67 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <ufs/ufs/ufsmount.h> |
#include <ufs/ufs/ufsmount.h> |
#include <ufs/ufs/ufs_extern.h> |
#include <ufs/ufs/ufs_extern.h> |
#include <ufs/ufs/ufs_bswap.h> |
#include <ufs/ufs/ufs_bswap.h> |
|
#include <ufs/ufs/ufs_wapbl.h> |
#include "fs_ffs.h" |
|
|
|
#ifdef DIAGNOSTIC |
#ifdef DIAGNOSTIC |
int dirchk = 1; |
int dirchk = 1; |
Line 158 ufs_lookup(void *v) |
|
Line 159 ufs_lookup(void *v) |
|
return (error); |
return (error); |
|
|
if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && |
if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) && |
(cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) |
(nameiop == DELETE || nameiop == RENAME)) |
return (EROFS); |
return (EROFS); |
|
|
/* |
/* |
Line 248 ufs_lookup(void *v) |
|
Line 249 ufs_lookup(void *v) |
|
} else { |
} else { |
dp->i_offset = dp->i_diroff; |
dp->i_offset = dp->i_diroff; |
if ((entryoffsetinblock = dp->i_offset & bmask) && |
if ((entryoffsetinblock = dp->i_offset & bmask) && |
(error = ufs_blkatoff(vdp, (off_t)dp->i_offset, NULL, &bp))) |
(error = ufs_blkatoff(vdp, (off_t)dp->i_offset, |
|
NULL, &bp, false))) |
goto out; |
goto out; |
numdirpasses = 2; |
numdirpasses = 2; |
nchstats.ncs_2passes++; |
nchstats.ncs_2passes++; |
|
|
if (bp != NULL) |
if (bp != NULL) |
brelse(bp, 0); |
brelse(bp, 0); |
error = ufs_blkatoff(vdp, (off_t)dp->i_offset, NULL, |
error = ufs_blkatoff(vdp, (off_t)dp->i_offset, NULL, |
&bp); |
&bp, false); |
if (error) |
if (error) |
goto out; |
goto out; |
entryoffsetinblock = 0; |
entryoffsetinblock = 0; |
|
|
dp->i_size = dp->i_offset + DIRSIZ(FSFMT(vdp), ep, needswap); |
dp->i_size = dp->i_offset + DIRSIZ(FSFMT(vdp), ep, needswap); |
DIP_ASSIGN(dp, size, dp->i_size); |
DIP_ASSIGN(dp, size, dp->i_size); |
dp->i_flag |= IN_CHANGE | IN_UPDATE; |
dp->i_flag |= IN_CHANGE | IN_UPDATE; |
|
UFS_WAPBL_UPDATE(vdp, NULL, NULL, UPDATE_DIROP); |
} |
} |
brelse(bp, 0); |
brelse(bp, 0); |
|
|
Line 689 ufs_dirbadentry(struct vnode *dp, struct |
|
Line 692 ufs_dirbadentry(struct vnode *dp, struct |
|
DIRSIZ(FSFMT(dp), ep, needswap) || |
DIRSIZ(FSFMT(dp), ep, needswap) || |
namlen > FFS_MAXNAMLEN) { |
namlen > FFS_MAXNAMLEN) { |
/*return (1); */ |
/*return (1); */ |
printf("First bad, reclen=%x, DIRSIZ=%lu, namlen=%d, flags=%x " |
printf("First bad, reclen=%#x, DIRSIZ=%lu, namlen=%d, " |
"entryoffsetinblock=%d, dirblksiz = %d\n", |
"flags=%#x, entryoffsetinblock=%d, dirblksiz = %d\n", |
ufs_rw16(ep->d_reclen, needswap), |
ufs_rw16(ep->d_reclen, needswap), |
(u_long)DIRSIZ(FSFMT(dp), ep, needswap), |
(u_long)DIRSIZ(FSFMT(dp), ep, needswap), |
namlen, dp->v_mount->mnt_flag, entryoffsetinblock,dirblksiz); |
namlen, dp->v_mount->mnt_flag, entryoffsetinblock, |
|
dirblksiz); |
goto bad; |
goto bad; |
} |
} |
if (ep->d_ino == 0) |
if (ep->d_ino == 0) |
Line 761 ufs_direnter(struct vnode *dvp, struct v |
|
Line 765 ufs_direnter(struct vnode *dvp, struct v |
|
const int needswap = UFS_MPNEEDSWAP(ump); |
const int needswap = UFS_MPNEEDSWAP(ump); |
int dirblksiz = ump->um_dirblksiz; |
int dirblksiz = ump->um_dirblksiz; |
|
|
|
UFS_WAPBL_JLOCK_ASSERT(dvp->v_mount); |
|
|
error = 0; |
error = 0; |
cr = cnp->cn_cred; |
cr = cnp->cn_cred; |
l = cnp->cn_lwp; |
l = curlwp; |
|
|
dp = VTOI(dvp); |
dp = VTOI(dvp); |
newentrysize = DIRSIZ(0, dirp, 0); |
newentrysize = DIRSIZ(0, dirp, 0); |
Line 881 ufs_direnter(struct vnode *dvp, struct v |
|
Line 887 ufs_direnter(struct vnode *dvp, struct v |
|
dp->i_size = dp->i_offset + dp->i_count; |
dp->i_size = dp->i_offset + dp->i_count; |
DIP_ASSIGN(dp, size, dp->i_size); |
DIP_ASSIGN(dp, size, dp->i_size); |
dp->i_flag |= IN_CHANGE | IN_UPDATE; |
dp->i_flag |= IN_CHANGE | IN_UPDATE; |
|
UFS_WAPBL_UPDATE(dvp, NULL, NULL, UPDATE_DIROP); |
} |
} |
/* |
/* |
* Get the block containing the space for the new directory entry. |
* Get the block containing the space for the new directory entry. |
*/ |
*/ |
error = ufs_blkatoff(dvp, (off_t)dp->i_offset, &dirbuf, &bp); |
error = ufs_blkatoff(dvp, (off_t)dp->i_offset, &dirbuf, &bp, true); |
if (error) { |
if (error) { |
if (DOINGSOFTDEP(dvp) && newdirbp != NULL) |
if (DOINGSOFTDEP(dvp) && newdirbp != NULL) |
bdwrite(newdirbp); |
bdwrite(newdirbp); |
Line 1009 ufs_direnter(struct vnode *dvp, struct v |
|
Line 1016 ufs_direnter(struct vnode *dvp, struct v |
|
if (dp->i_dirhash != NULL) |
if (dp->i_dirhash != NULL) |
ufsdirhash_dirtrunc(dp, dp->i_endoff); |
ufsdirhash_dirtrunc(dp, dp->i_endoff); |
#endif |
#endif |
(void) UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cr, l); |
(void) UFS_TRUNCATE(dvp, (off_t)dp->i_endoff, IO_SYNC, cr); |
if (DOINGSOFTDEP(dvp) && (tvp != NULL)) |
if (DOINGSOFTDEP(dvp) && (tvp != NULL)) |
vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); |
vn_lock(tvp, LK_EXCLUSIVE | LK_RETRY); |
} |
} |
|
UFS_WAPBL_UPDATE(dvp, NULL, NULL, UPDATE_DIROP); |
return (error); |
return (error); |
} |
} |
|
|
Line 1039 ufs_dirremove(struct vnode *dvp, struct |
|
Line 1047 ufs_dirremove(struct vnode *dvp, struct |
|
const int needswap = UFS_MPNEEDSWAP(dp->i_ump); |
const int needswap = UFS_MPNEEDSWAP(dp->i_ump); |
#endif |
#endif |
|
|
|
UFS_WAPBL_JLOCK_ASSERT(dvp->v_mount); |
|
|
if (flags & DOWHITEOUT) { |
if (flags & DOWHITEOUT) { |
/* |
/* |
* Whiteout entry: set d_ino to WINO. |
* Whiteout entry: set d_ino to WINO. |
*/ |
*/ |
error = ufs_blkatoff(dvp, (off_t)dp->i_offset, (void *)&ep, |
error = ufs_blkatoff(dvp, (off_t)dp->i_offset, (void *)&ep, |
&bp); |
&bp, true); |
if (error) |
if (error) |
return (error); |
return (error); |
ep->d_ino = ufs_rw32(WINO, needswap); |
ep->d_ino = ufs_rw32(WINO, needswap); |
Line 1053 ufs_dirremove(struct vnode *dvp, struct |
|
Line 1063 ufs_dirremove(struct vnode *dvp, struct |
|
} |
} |
|
|
if ((error = ufs_blkatoff(dvp, |
if ((error = ufs_blkatoff(dvp, |
(off_t)(dp->i_offset - dp->i_count), (void *)&ep, &bp)) != 0) |
(off_t)(dp->i_offset - dp->i_count), (void *)&ep, &bp, true)) != 0) |
return (error); |
return (error); |
|
|
#ifdef UFS_DIRHASH |
#ifdef UFS_DIRHASH |
|
|
ip->i_nlink--; |
ip->i_nlink--; |
DIP_ASSIGN(ip, nlink, ip->i_nlink); |
DIP_ASSIGN(ip, nlink, ip->i_nlink); |
ip->i_flag |= IN_CHANGE; |
ip->i_flag |= IN_CHANGE; |
|
UFS_WAPBL_UPDATE(ITOV(ip), NULL, NULL, 0); |
} |
} |
error = VOP_BWRITE(bp); |
error = VOP_BWRITE(bp); |
} |
} |
|
|
if (ip != 0 && (ip->i_flags & SF_SNAPSHOT) != 0 && |
if (ip != 0 && (ip->i_flags & SF_SNAPSHOT) != 0 && |
ip->i_ffs_effnlink == 0) |
ip->i_ffs_effnlink == 0) |
ffs_snapgone(ip); |
ffs_snapgone(ip); |
|
UFS_WAPBL_UPDATE(dvp, NULL, NULL, 0); |
#endif |
#endif |
return (error); |
return (error); |
} |
} |
Line 1135 ufs_dirrewrite(struct inode *dp, struct |
|
Line 1147 ufs_dirrewrite(struct inode *dp, struct |
|
struct vnode *vdp = ITOV(dp); |
struct vnode *vdp = ITOV(dp); |
int error; |
int error; |
|
|
error = ufs_blkatoff(vdp, (off_t)dp->i_offset, (void *)&ep, &bp); |
error = ufs_blkatoff(vdp, (off_t)dp->i_offset, (void *)&ep, &bp, true); |
if (error) |
if (error) |
return (error); |
return (error); |
ep->d_ino = ufs_rw32(newinum, UFS_MPNEEDSWAP(dp->i_ump)); |
ep->d_ino = ufs_rw32(newinum, UFS_MPNEEDSWAP(dp->i_ump)); |
Line 1150 ufs_dirrewrite(struct inode *dp, struct |
|
Line 1162 ufs_dirrewrite(struct inode *dp, struct |
|
oip->i_nlink--; |
oip->i_nlink--; |
DIP_ASSIGN(oip, nlink, oip->i_nlink); |
DIP_ASSIGN(oip, nlink, oip->i_nlink); |
oip->i_flag |= IN_CHANGE; |
oip->i_flag |= IN_CHANGE; |
|
UFS_WAPBL_UPDATE(ITOV(oip), NULL, NULL, UPDATE_DIROP); |
error = VOP_BWRITE(bp); |
error = VOP_BWRITE(bp); |
} |
} |
dp->i_flag |= iflags; |
dp->i_flag |= iflags; |
Line 1161 ufs_dirrewrite(struct inode *dp, struct |
|
Line 1174 ufs_dirrewrite(struct inode *dp, struct |
|
*/ |
*/ |
if ((oip->i_flags & SF_SNAPSHOT) != 0 && oip->i_ffs_effnlink == 0) |
if ((oip->i_flags & SF_SNAPSHOT) != 0 && oip->i_ffs_effnlink == 0) |
ffs_snapgone(oip); |
ffs_snapgone(oip); |
|
UFS_WAPBL_UPDATE(vdp, NULL, NULL, UPDATE_DIROP); |
#endif |
#endif |
return (error); |
return (error); |
} |
} |
Line 1312 int ufs_dirrablks = UFS_DIRRABLKS; |
|
Line 1326 int ufs_dirrablks = UFS_DIRRABLKS; |
|
/* |
/* |
* ufs_blkatoff: Return buffer with the contents of block "offset" from |
* ufs_blkatoff: Return buffer with the contents of block "offset" from |
* the beginning of directory "vp". If "res" is non-zero, fill it in with |
* the beginning of directory "vp". If "res" is non-zero, fill it in with |
* a pointer to the remaining space in the directory. |
* a pointer to the remaining space in the directory. If the caller intends |
|
* to modify the buffer returned, "modify" must be true. |
*/ |
*/ |
|
|
int |
int |
ufs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp) |
ufs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp, |
|
bool modify) |
{ |
{ |
struct inode *ip; |
struct inode *ip; |
struct buf *bp; |
struct buf *bp; |
Line 1330 ufs_blkatoff(struct vnode *vp, off_t off |
|
Line 1346 ufs_blkatoff(struct vnode *vp, off_t off |
|
const int bsize = 1 << bshift; |
const int bsize = 1 << bshift; |
off_t eof; |
off_t eof; |
|
|
blks = kmem_alloc((1+dirrablks) * sizeof(daddr_t), KM_SLEEP); |
blks = kmem_alloc((1 + dirrablks) * sizeof(daddr_t), KM_SLEEP); |
blksizes = kmem_alloc((1+dirrablks) * sizeof(int), KM_SLEEP); |
blksizes = kmem_alloc((1 + dirrablks) * sizeof(int), KM_SLEEP); |
ip = VTOI(vp); |
ip = VTOI(vp); |
KASSERT(vp->v_size == ip->i_size); |
KASSERT(vp->v_size == ip->i_size); |
GOP_SIZE(vp, vp->v_size, &eof, 0); |
GOP_SIZE(vp, vp->v_size, &eof, 0); |
Line 1355 ufs_blkatoff(struct vnode *vp, off_t off |
|
Line 1371 ufs_blkatoff(struct vnode *vp, off_t off |
|
} |
} |
KASSERT(run >= 1); |
KASSERT(run >= 1); |
error = breadn(vp, blks[0], blksizes[0], &blks[1], &blksizes[1], |
error = breadn(vp, blks[0], blksizes[0], &blks[1], &blksizes[1], |
run - 1, NOCRED, &bp); |
run - 1, NOCRED, (modify ? B_MODIFY : 0), &bp); |
if (error != 0) { |
if (error != 0) { |
brelse(bp, 0); |
brelse(bp, 0); |
*bpp = NULL; |
*bpp = NULL; |
Line 1367 ufs_blkatoff(struct vnode *vp, off_t off |
|
Line 1383 ufs_blkatoff(struct vnode *vp, off_t off |
|
*bpp = bp; |
*bpp = bp; |
|
|
out: |
out: |
kmem_free(blks, (1+dirrablks) * sizeof(daddr_t)); |
kmem_free(blks, (1 + dirrablks) * sizeof(daddr_t)); |
kmem_free(blksizes, (1+dirrablks) * sizeof(int)); |
kmem_free(blksizes, (1 + dirrablks) * sizeof(int)); |
return error; |
return error; |
} |
} |