Tidy up ulfs_direnter: don't malloc a temporary struct lfs_direct

and double-copy it. Just write to the destination buffer.
This commit is contained in:
dholland 2015-09-15 15:00:49 +00:00
parent 54671fde93
commit 53a3e07718
1 changed files with 45 additions and 39 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ulfs_lookup.c,v 1.28 2015/09/15 15:00:32 dholland Exp $ */
/* $NetBSD: ulfs_lookup.c,v 1.29 2015/09/15 15:00:49 dholland Exp $ */
/* from NetBSD: ufs_lookup.c,v 1.122 2013/01/22 09:39:18 dholland Exp */
/*
@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.28 2015/09/15 15:00:32 dholland Exp $");
__KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.29 2015/09/15 15:00:49 dholland Exp $");
#ifdef _KERNEL_OPT
#include "opt_lfs.h"
@ -696,26 +696,29 @@ bad:
}
/*
* Construct a new directory entry after a call to namei, using the
* name in the componentname argument cnp. The new directory entry
* will refer to inode INUM which has type (directory-level type)
* DTYPE. If adding a reference to an already-created or
* already-extant inode, these values are retrieved with:
* ip->i_number
* LFS_IFTODT(ip->i_mode)
* (The latter should be tidier. XXX)
* Assign the contents of directory entry DIRP, on volume FS.
*
* NAME/NAMLEN is the name, which is not necessarily null terminated.
* INUM is the inode number, and DTYPE is the type code (LFS_DT_*).
*
* Note that these values typically come from:
* cnp->cn_nameptr
* cnp->cn_namelen
* ip->i_number
* LFS_IFTODT(ip->i_mode)
*
* Does not set d_reclen.
*/
static void
ulfs_makedirentry_tmp(struct lfs *fs, struct componentname *cnp,
ino_t inum, unsigned dtype, struct lfs_direct *newdirp)
ulfs_direntry_assign(struct lfs *fs, struct lfs_direct *dirp,
const char *name, size_t namlen,
ino_t inum, unsigned dtype)
{
lfs_dir_setino(fs, newdirp, inum);
memcpy(newdirp->d_name, cnp->cn_nameptr, (size_t)cnp->cn_namelen);
newdirp->d_name[cnp->cn_namelen] = '\0';
lfs_dir_setnamlen(fs, newdirp, cnp->cn_namelen);
lfs_dir_settype(fs, newdirp, dtype);
lfs_dir_setino(fs, dirp, inum);
lfs_dir_setnamlen(fs, dirp, namlen);
lfs_dir_settype(fs, dirp, dtype);
memcpy(dirp->d_name, name, namlen);
dirp->d_name[namlen] = '\0';
}
/*
@ -766,16 +769,19 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr,
struct ulfsmount *ump = VFSTOULFS(dvp->v_mount);
struct lfs *fs = ump->um_lfs;
int dirblksiz = fs->um_dirblksiz;
struct lfs_direct *dirp;
dirp = pool_cache_get(ulfs_direct_cache, PR_WAITOK);
ulfs_makedirentry_tmp(fs, cnp, inum, dtype, dirp);
const char *name;
unsigned namlen, reclen;
#ifdef LFS_DIRHASH
int dohashadd;
#endif
error = 0;
name = cnp->cn_nameptr; /* note: not null-terminated */
namlen = cnp->cn_namelen;
cr = cnp->cn_cred;
dp = VTOI(dvp);
newentrysize = LFS_DIRSIZ(fs, dirp);
newentrysize = LFS_DIRECTSIZ(namlen);
if (ulr->ulr_count == 0) {
/*
@ -788,7 +794,6 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr,
panic("ulfs_direnter: newblk");
if ((error = lfs_balloc(dvp, (off_t)ulr->ulr_offset, dirblksiz,
cr, B_CLRBUF | B_SYNC, &bp)) != 0) {
pool_cache_put(ulfs_direct_cache, dirp);
return (error);
}
dp->i_size = ulr->ulr_offset + dirblksiz;
@ -796,11 +801,13 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr,
dp->i_flag |= IN_CHANGE | IN_UPDATE;
uvm_vnp_setsize(dvp, dp->i_size);
lfs_blkoff = ulr->ulr_offset & (ump->um_mountp->mnt_stat.f_iosize - 1);
memcpy((char *)bp->b_data + lfs_blkoff, dirp, newentrysize);
ep = (struct lfs_direct *)((char *)bp->b_data + lfs_blkoff);
ulfs_direntry_assign(fs, ep, name, namlen, inum, dtype);
lfs_dir_setreclen(fs, ep, dirblksiz);
#ifdef LFS_DIRHASH
if (dp->i_dirhash != NULL) {
ulfsdirhash_newblk(dp, ulr->ulr_offset);
ulfsdirhash_add(dp, dirp, ulr->ulr_offset);
ulfsdirhash_add(dp, ep, ulr->ulr_offset);
ulfsdirhash_checkblock(dp, (char *)bp->b_data + lfs_blkoff,
ulr->ulr_offset);
}
@ -808,7 +815,6 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr,
error = VOP_BWRITE(bp->b_vp, bp);
vfs_timestamp(&ts);
ret = lfs_update(dvp, &ts, &ts, UPDATE_DIROP);
pool_cache_put(ulfs_direct_cache, dirp);
if (error == 0)
return (ret);
return (error);
@ -844,7 +850,6 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr,
*/
error = ulfs_blkatoff(dvp, (off_t)ulr->ulr_offset, &dirbuf, &bp, true);
if (error) {
pool_cache_put(ulfs_direct_cache, dirp);
return (error);
}
/*
@ -857,8 +862,6 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr,
dsize = (lfs_dir_getino(fs, ep) != 0) ? LFS_DIRSIZ(fs, ep) : 0;
spacefree = lfs_dir_getreclen(fs, ep) - dsize;
for (loc = lfs_dir_getreclen(fs, ep); loc < ulr->ulr_count; ) {
uint16_t reclen;
nep = (struct lfs_direct *)(dirbuf + loc);
/* Trim the existing slot (NB: dsize may be zero). */
@ -902,25 +905,29 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr,
*/
if (lfs_dir_getino(fs, ep) == 0 ||
(lfs_dir_getino(fs, ep) == ULFS_WINO &&
memcmp(ep->d_name, dirp->d_name, lfs_dir_getnamlen(fs, dirp)) == 0)) {
memcmp(ep->d_name, name, namlen) == 0)) {
if (spacefree + dsize < newentrysize)
panic("ulfs_direnter: compact1");
lfs_dir_setreclen(fs, dirp, spacefree + dsize);
reclen = spacefree + dsize;
#ifdef LFS_DIRHASH
dohashadd = (lfs_dir_getino(fs, ep) == 0);
#endif
} else {
if (spacefree < newentrysize)
panic("ulfs_direnter: compact2");
lfs_dir_setreclen(fs, dirp, spacefree);
reclen = spacefree;
lfs_dir_setreclen(fs, ep, dsize);
ep = LFS_NEXTDIR(fs, ep);
#ifdef LFS_DIRHASH
dohashadd = 1;
#endif
}
ulfs_direntry_assign(fs, ep, name, namlen, inum, dtype);
lfs_dir_setreclen(fs, ep, reclen);
#ifdef LFS_DIRHASH
if (dp->i_dirhash != NULL && (lfs_dir_getino(fs, ep) == 0 ||
lfs_dir_getreclen(fs, dirp) == spacefree))
ulfsdirhash_add(dp, dirp, ulr->ulr_offset + ((char *)ep - dirbuf));
#endif
memcpy((void *)ep, (void *)dirp, (u_int)newentrysize);
#ifdef LFS_DIRHASH
if (dp->i_dirhash != NULL && dohashadd)
ulfsdirhash_add(dp, ep, ulr->ulr_offset + ((char *)ep - dirbuf));
if (dp->i_dirhash != NULL)
ulfsdirhash_checkblock(dp, dirbuf -
(ulr->ulr_offset & (dirblksiz - 1)),
@ -942,7 +949,6 @@ ulfs_direnter(struct vnode *dvp, const struct ulfs_lookup_results *ulr,
#endif
(void) lfs_truncate(dvp, (off_t)ulr->ulr_endoff, IO_SYNC, cr);
}
pool_cache_put(ulfs_direct_cache, dirp);
return (error);
}