factoring out "at" syscalls common code in nlookup

看板DFBSD_kernel作者時間16年前 (2009/07/27 10:01), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串3/3 (看更多)
Hello, As part of implementing the at family of syscalls (openat(), fstatat(), ...), I propose to put the common code handling the file descriptor argument in the namecache as shown in the patch below. Any objection? Cheers, Nicolas --- sys/kern/vfs_nlookup.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ sys/kern/vfs_syscalls.c | 32 +++--------------------------- sys/sys/nlookup.h | 3 ++ 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/sys/kern/vfs_nlookup.c b/sys/kern/vfs_nlookup.c index 09758a6..4e1552a 100644 --- a/sys/kern/vfs_nlookup.c +++ b/sys/kern/vfs_nlookup.c @@ -65,6 +65,7 @@ #include <sys/malloc.h> #include <sys/stat.h> #include <sys/objcache.h> +#include <sys/file.h> #ifdef KTRACE #include <sys/ktrace.h> @@ -128,6 +129,49 @@ nlookup_init(struct nlookupdata *nd, return(error); } + +/* + * nlookup_init() for "at" family of syscalls. + * + * Works similarly to nlookup_init() but if path is relative and fd is not + * AT_FDCWD, path is interpreted relative to the directory pointed to by fd. + * + * Takes a ref on the file entry pointed to by fd that will be dropped by + * nlookup_done(). + */ +int +nlookup_init_at(struct nlookupdata *nd, int fd, const char *path, + enum uio_seg seg, int flags) +{ + struct thread *td = curthread; + struct proc *p = td->td_proc; + struct file* fp; + struct vnode *vp; + int error; + + if ((error = nlookup_init(nd, path, seg, flags)) != 0) + return (error); + + if (nd->nl_path[0] != '/' && fd != AT_FDCWD) { + if ((error = holdvnode(p->p_fd, fd, &fp)) != 0) + goto done; + nd->nl_atfp = fp; + vp = (struct vnode*)fp->f_data; + if (vp->v_type != VDIR || fp->f_nchandle.ncp == NULL) { + error = ENOTDIR; + goto done; + } + cache_drop(&nd->nl_nch); + cache_copy(&fp->f_nchandle, &nd->nl_nch); + } + +done: + if (error) + nlookup_done(nd); + return (error); + +} + /* * This works similarly to nlookup_init() but does not assume a process * context. rootnch is always chosen for the root directory and the cred @@ -229,6 +273,10 @@ nlookup_done(struct nlookupdata *nd) vrele(nd->nl_dvp); nd->nl_dvp = NULL; } + if (nd->nl_atfp) { + fdrop(nd->nl_atfp); + nd->nl_atfp = NULL; + } nd->nl_flags = 0; /* clear remaining flags (just clear everything) */ } diff --git a/sys/sys/nlookup.h b/sys/sys/nlookup.h index cec3b96..cc709cc 100644 --- a/sys/sys/nlookup.h +++ b/sys/sys/nlookup.h @@ -85,6 +85,8 @@ struct nlookupdata { int nl_flags; /* operations flags */ int nl_loopcnt; /* symlinks encountered */ + struct file *nl_atfp; /* refs nlookup_init_at() fd or NULL */ + /* * These fields are populated by vn_open(). nlookup_done() will * vn_close() a non-NULL vp so if you extract it be sure to NULL out @@ -144,6 +146,7 @@ struct nlookupdata { #ifdef _KERNEL int nlookup_init(struct nlookupdata *, const char *, enum uio_seg, int); +int nlookup_init_at(struct nlookupdata *, int, const char *, enum uio_seg, int); int nlookup_init_raw(struct nlookupdata *, const char *, enum uio_seg, int, struct ucred *, struct nchandle *); void nlookup_set_cred(struct nlookupdata *nd, struct ucred *cred); void nlookup_zero(struct nlookupdata *); -- 1.6.0
文章代碼(AID): #1ARGfjXX (DFBSD_kernel)
文章代碼(AID): #1ARGfjXX (DFBSD_kernel)