diff --git a/libexec/lfs_cleanerd/Makefile b/libexec/lfs_cleanerd/Makefile index 30f33a0b23c2..dedc5f65a3ea 100644 --- a/libexec/lfs_cleanerd/Makefile +++ b/libexec/lfs_cleanerd/Makefile @@ -1,24 +1,10 @@ -# $NetBSD: Makefile,v 1.14 2009/06/21 20:20:50 christos Exp $ +# $NetBSD: Makefile,v 1.15 2009/08/06 00:51:55 pooka Exp $ # @(#)Makefile 8.1 (Berkeley) 6/18/93 -WARNS?=3 # XXX: too many sign-compare issues - -.include +.include "Makefile.inc" PROG= lfs_cleanerd -SRCS= lfs_cleanerd.c fdfs.c coalesce.c cleansrv.c -SRCS+= lfs_cksum.c -SRCS+= bufcache.c vnode.c lfs.c # segwrite.c MAN= lfs_cleanerd.8 -.PATH: ${NETBSDSRCDIR}/sys/ufs/lfs ${NETBSDSRCDIR}/sbin/fsck_lfs - -FSCK_LFS= ${NETBSDSRCDIR}/sbin/fsck_lfs -DPADD= ${LIBUTIL} -LDADD= -lutil -CPPFLAGS+=-I${FSCK_LFS} "-Dmutex_enter(x)=" "-Dmutex_exit(x)=" # -DUSE_CLIENT_SERVER -CPPFLAGS+="-DKASSERT(x)=" -#CPPFLAGS+=-DREPAIR_ZERO_FINFO -#CPPFLAGS+=-DTEST_PATTERN BINDIR= /libexec .if (${MKDYNAMICROOT} == "no") diff --git a/libexec/lfs_cleanerd/Makefile.inc b/libexec/lfs_cleanerd/Makefile.inc new file mode 100644 index 000000000000..2fec757b1945 --- /dev/null +++ b/libexec/lfs_cleanerd/Makefile.inc @@ -0,0 +1,21 @@ +# $NetBSD: Makefile.inc,v 1.1 2009/08/06 00:51:55 pooka Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/18/93 + +WARNS?=3 # XXX: too many sign-compare issues + +.include + +SRCS= lfs_cleanerd.c fdfs.c coalesce.c cleansrv.c +SRCS+= lfs_cksum.c +SRCS+= bufcache.c vnode.c lfs.c kernelops.c # segwrite.c +.PATH: ${NETBSDSRCDIR}/sys/ufs/lfs ${NETBSDSRCDIR}/sbin/fsck_lfs \ + ${NETBSDSRCDIR}/libexec/lfs_cleanerd + +FSCK_LFS= ${NETBSDSRCDIR}/sbin/fsck_lfs +DPADD= ${LIBUTIL} +LDADD= -lutil +CPPFLAGS+=-I${FSCK_LFS} -I${NETBSDSRCDIR}/sbin/mount_lfs # -DUSE_CLIENT_SERVER +CPPFLAGS+="-Dmutex_enter(x)=" "-Dmutex_exit(x)=" +CPPFLAGS+="-DKASSERT(x)=" +#CPPFLAGS+=-DREPAIR_ZERO_FINFO +#CPPFLAGS+=-DTEST_PATTERN diff --git a/libexec/lfs_cleanerd/coalesce.c b/libexec/lfs_cleanerd/coalesce.c index cd74c29b8443..96a500e23918 100644 --- a/libexec/lfs_cleanerd/coalesce.c +++ b/libexec/lfs_cleanerd/coalesce.c @@ -1,4 +1,4 @@ -/* $NetBSD: coalesce.c,v 1.17 2009/03/16 00:08:10 lukem Exp $ */ +/* $NetBSD: coalesce.c,v 1.18 2009/08/06 00:51:55 pooka Exp $ */ /*- * Copyright (c) 2002, 2005 The NetBSD Foundation, Inc. @@ -56,6 +56,7 @@ #include "bufcache.h" #include "vnode.h" #include "cleaner.h" +#include "kernelops.h" extern int debug, do_mmap; @@ -197,7 +198,7 @@ clean_inode(struct clfs *fs, ino_t ino) } lim.blkiov = bip; lim.blkcnt = nb; - if (fcntl(fs->clfs_ifilefd, LFCNBMAPV, &lim) < 0) { + if (kops.ko_fcntl(fs->clfs_ifilefd, LFCNBMAPV, &lim) < 0) { syslog(LOG_WARNING, "%s: coalesce: LFCNBMAPV: %m", fs->lfs_fsmnt); retval = COALESCE_BADBMAPV; @@ -277,7 +278,7 @@ clean_inode(struct clfs *fs, ino_t ino) goto out; } - if (pread(fs->clfs_devfd, bip[i].bi_bp, bip[i].bi_size, + if (kops.ko_pread(fs->clfs_devfd, bip[i].bi_bp, bip[i].bi_size, fsbtob(fs, bip[i].bi_daddr)) < 0) { retval = COALESCE_EIO; goto out; @@ -300,12 +301,13 @@ clean_inode(struct clfs *fs, ino_t ino) brelse(bp, B_INVAL); if (cip.clean < 4) /* XXX magic number 4 */ - fcntl(fs->clfs_ifilefd, LFCNSEGWAIT, NULL); + kops.ko_fcntl(fs->clfs_ifilefd, + LFCNSEGWAIT, NULL); } while(cip.clean < 4); lim.blkiov = tbip; lim.blkcnt = (tbip + bps < bip + nb ? bps : nb % bps); - if (fcntl(fs->clfs_ifilefd, LFCNMARKV, &lim) < 0) { + if (kops.ko_fcntl(fs->clfs_ifilefd, LFCNMARKV, &lim) < 0) { retval = COALESCE_BADMARKV; goto out; } diff --git a/libexec/lfs_cleanerd/fdfs.c b/libexec/lfs_cleanerd/fdfs.c index ff670dc539ff..ff0a02a42079 100644 --- a/libexec/lfs_cleanerd/fdfs.c +++ b/libexec/lfs_cleanerd/fdfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: fdfs.c,v 1.6 2008/04/28 20:23:04 martin Exp $ */ +/* $NetBSD: fdfs.c,v 1.7 2009/08/06 00:51:55 pooka Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -52,6 +52,7 @@ #include "vnode.h" #include "bufcache.h" #include "fdfs.h" +#include "kernelops.h" /* * Return a "vnode" interface to a given file descriptor. @@ -202,7 +203,7 @@ fd_preload(struct uvnode *vp, daddr_t start) fs->fd_bufp[fs->fd_bufi].start = start; fs->fd_bufp[fs->fd_bufi].end = start + fs->fd_ssize / fs->fd_bsize; - if ((r = pread(fs->fd_fd, fs->fd_bufp[fs->fd_bufi].buf, + if ((r = kops.ko_pread(fs->fd_fd, fs->fd_bufp[fs->fd_bufi].buf, (size_t)fs->fd_ssize, start * fs->fd_bsize)) < 0) { syslog(LOG_ERR, "preload to segment buffer %d", fs->fd_bufi); return r; @@ -250,12 +251,12 @@ fd_vop_strategy(struct ubuf * bp) bp->b_flags |= (B_DONTFREE | B_DONE); return 0; } - count = pread(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, + count = kops.ko_pread(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, bp->b_blkno * fs->fd_bsize); if (count == bp->b_bcount) bp->b_flags |= B_DONE; } else { - count = pwrite(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, + count = kops.ko_pwrite(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, bp->b_blkno * fs->fd_bsize); if (count == 0) { perror("pwrite"); diff --git a/libexec/lfs_cleanerd/lfs_cleanerd.c b/libexec/lfs_cleanerd/lfs_cleanerd.c index 98d96c814575..b42d217666f4 100644 --- a/libexec/lfs_cleanerd/lfs_cleanerd.c +++ b/libexec/lfs_cleanerd/lfs_cleanerd.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_cleanerd.c,v 1.20 2009/08/06 00:23:08 pooka Exp $ */ +/* $NetBSD: lfs_cleanerd.c,v 1.21 2009/08/06 00:51:55 pooka Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -57,6 +57,8 @@ #include "lfs_user.h" #include "fdfs.h" #include "cleaner.h" +#include "kernelops.h" +#include "mount_lfs.h" /* * Global variables. @@ -134,8 +136,8 @@ reinit_fs(struct clfs *fs) char fsname[MNAMELEN]; strncpy(fsname, (char *)fs->lfs_fsmnt, MNAMELEN); - close(fs->clfs_ifilefd); - close(fs->clfs_devfd); + kops.ko_close(fs->clfs_ifilefd); + kops.ko_close(fs->clfs_devfd); fd_reclaim(fs->clfs_devvp); fd_reclaim(fs->lfs_ivnode); free(fs->clfs_dev); @@ -157,7 +159,7 @@ init_unmounted_fs(struct clfs *fs, char *fsname) int i; fs->clfs_dev = fsname; - if ((fs->clfs_devfd = open(fs->clfs_dev, O_RDWR)) < 0) { + if ((fs->clfs_devfd = kops.ko_open(fs->clfs_dev, O_RDWR)) < 0) { syslog(LOG_ERR, "couldn't open device %s read/write", fs->clfs_dev); return -1; @@ -207,7 +209,7 @@ init_fs(struct clfs *fs, char *fsname) * XXX this is ugly. Is there a way to discover the raw device * XXX for a given mount point? */ - if (statvfs(fsname, &sf) < 0) + if (kops.ko_statvfs(fsname, &sf, ST_WAIT) < 0) return -1; fs->clfs_dev = malloc(strlen(sf.f_mntfromname) + 2); if (fs->clfs_dev == NULL) { @@ -215,24 +217,24 @@ init_fs(struct clfs *fs, char *fsname) return -1; } sprintf(fs->clfs_dev, "/dev/r%s", sf.f_mntfromname + 5); - if ((fs->clfs_devfd = open(fs->clfs_dev, O_RDONLY)) < 0) { + if ((fs->clfs_devfd = kops.ko_open(fs->clfs_dev, O_RDONLY, 0)) < 0) { syslog(LOG_ERR, "couldn't open device %s for reading", fs->clfs_dev); return -1; } /* Find the Ifile and open it */ - if ((rootfd = open(fsname, O_RDONLY)) < 0) + if ((rootfd = kops.ko_open(fsname, O_RDONLY, 0)) < 0) return -2; - if (fcntl(rootfd, LFCNIFILEFH, &fs->clfs_ifilefh) < 0) + if (kops.ko_fcntl(rootfd, LFCNIFILEFH, &fs->clfs_ifilefh) < 0) return -3; - if ((fs->clfs_ifilefd = fhopen(&fs->clfs_ifilefh, + if ((fs->clfs_ifilefd = kops.ko_fhopen(&fs->clfs_ifilefh, sizeof(fs->clfs_ifilefh), O_RDONLY)) < 0) return -4; - close(rootfd); + kops.ko_close(rootfd); /* Load in the superblock */ - if (pread(fs->clfs_devfd, &(fs->lfs_dlfs), sizeof(struct dlfs), + if (kops.ko_pread(fs->clfs_devfd, &(fs->lfs_dlfs), sizeof(struct dlfs), LFS_LABELPAD) < 0) return -1; @@ -798,7 +800,7 @@ toss_old_blocks(struct clfs *fs, BLOCK_INFO **bipp, int *bic, int *sizep) /* Use bmapv to locate the blocks */ lim.blkiov = bip; lim.blkcnt = *bic; - if ((r = fcntl(fs->clfs_ifilefd, LFCNBMAPV, &lim)) < 0) { + if ((r = kops.ko_fcntl(fs->clfs_ifilefd, LFCNBMAPV, &lim)) < 0) { syslog(LOG_WARNING, "%s: bmapv returned %d (%m)", fs->lfs_fsmnt, r); return; @@ -859,7 +861,7 @@ invalidate_segment(struct clfs *fs, int sn) */ lim.blkiov = bip; lim.blkcnt = bic; - if ((r = fcntl(fs->clfs_ifilefd, LFCNMARKV, &lim)) < 0) { + if ((r = kops.ko_fcntl(fs->clfs_ifilefd, LFCNMARKV, &lim)) < 0) { syslog(LOG_WARNING, "%s: markv returned %d (%m) " "for seg %d", fs->lfs_fsmnt, r, sn); return r; @@ -868,7 +870,7 @@ invalidate_segment(struct clfs *fs, int sn) /* * Finally call invalidate to invalidate the segment. */ - if ((r = fcntl(fs->clfs_ifilefd, LFCNINVAL, &sn)) < 0) { + if ((r = kops.ko_fcntl(fs->clfs_ifilefd, LFCNINVAL, &sn)) < 0) { syslog(LOG_WARNING, "%s: inval returned %d (%m) " "for seg %d", fs->lfs_fsmnt, r, sn); return r; @@ -1129,7 +1131,7 @@ clean_fs(struct clfs *fs, CLEANERINFO *cip) } #endif /* TEST_PATTERN */ dlog("sending blocks %d-%d", mc, mc + lim.blkcnt - 1); - if ((r = fcntl(fs->clfs_ifilefd, LFCNMARKV, &lim)) < 0) { + if ((r = kops.ko_fcntl(fs->clfs_ifilefd, LFCNMARKV, &lim))<0) { syslog(LOG_WARNING, "%s: markv returned %d (%m)", fs->lfs_fsmnt, r); if (errno != EAGAIN && errno != ESHUTDOWN) { @@ -1158,7 +1160,7 @@ clean_fs(struct clfs *fs, CLEANERINFO *cip) /* * Finally call reclaim to prompt cleaning of the segments. */ - fcntl(fs->clfs_ifilefd, LFCNRECLAIM, NULL); + kops.ko_fcntl(fs->clfs_ifilefd, LFCNRECLAIM, NULL); fd_release_all(fs->clfs_devvp); return 0; @@ -1309,11 +1311,20 @@ usage(void) "[-n nsegs] [-r report_freq] [-t timeout] fs_name ..."); } +#ifndef LFS_CLEANER_AS_LIB /* * Main. */ int main(int argc, char **argv) +{ + + return lfs_cleaner_main(argc, argv); +} +#endif + +int +lfs_cleaner_main(int argc, char **argv) { int i, opt, error, r, loopcount, nodetach; struct timeval tv; @@ -1538,7 +1549,7 @@ main(int argc, char **argv) } while(cleaned_one); tv.tv_sec = segwait_timeout; tv.tv_usec = 0; - error = fcntl(fsp[0]->clfs_ifilefd, LFCNSEGWAITALL, &tv); + error = kops.ko_fcntl(fsp[0]->clfs_ifilefd,LFCNSEGWAITALL,&tv); if (error) err(1, "LFCNSEGWAITALL"); } diff --git a/sbin/fsck_lfs/Makefile b/sbin/fsck_lfs/Makefile index 839d1b4c7552..83f2dbccf4af 100644 --- a/sbin/fsck_lfs/Makefile +++ b/sbin/fsck_lfs/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.16 2009/04/11 07:58:12 lukem Exp $ +# $NetBSD: Makefile,v 1.17 2009/08/06 00:51:55 pooka Exp $ # @(#)Makefile 8.1 (Berkeley) 6/5/93 WARNS?= 3 # XXX: sign-compare issues @@ -10,6 +10,7 @@ MAN= fsck_lfs.8 SRCS= bufcache.c dir.c fsutil.c inode.c lfs.c lfs_cksum.c lfs_itimes.c main.c SRCS+= pass0.c pass1.c pass2.c pass3.c pass4.c pass5.c pass6.c SRCS+= segwrite.c setup.c utilities.c vars.c vnode.c +SRCS+= kernelops.c FSCK= ${NETBSDSRCDIR}/sbin/fsck .PATH: ${NETBSDSRCDIR}/sys/ufs/lfs ${FSCK} CPPFLAGS+=-I${.CURDIR} -I${FSCK} -DIN_FSCK_LFS "-Dmutex_enter(x)=" "-Dmutex_exit(x)=" diff --git a/sbin/fsck_lfs/kernelops.c b/sbin/fsck_lfs/kernelops.c new file mode 100644 index 000000000000..e59215863163 --- /dev/null +++ b/sbin/fsck_lfs/kernelops.c @@ -0,0 +1,80 @@ +/* $NetBSD: kernelops.c,v 1.1 2009/08/06 00:51:55 pooka Exp $ */ + +/* + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#ifndef lint +__RCSID("$NetBSD: kernelops.c,v 1.1 2009/08/06 00:51:55 pooka Exp $"); +#endif /* !lint */ + +/* + * Select operations vector for kernel communication -- either regular + * system calls or rump system calls. The latter are use when the + * cleaner is run as part of rump_lfs. + * + * The selection is controlled by an ifdef for now, since I see no + * value in making it dynamic. + */ + +#include +#include +#include + +#include +#include + +#include "kernelops.h" + +#ifdef USE_RUMP + +#include +#include + +struct kernelops kops = { + .ko_open = rump_sys_open, + .ko_fcntl = rump_sys_fcntl, + .ko_statvfs = rump_sys_statvfs1, + .ko_fhopen = rump_sys_fhopen, + .ko_close = rump_sys_close, + + .ko_pread = rump_sys_pread, + .ko_pwrite = rump_sys_pwrite, +}; + +#else + +struct kernelops kops = { + .ko_open = (void *)open, /* XXX: fix rump_syscalls */ + .ko_fcntl = (void *)fcntl, + .ko_statvfs = statvfs1, + .ko_fhopen = fhopen, + .ko_close = close, + + .ko_pread = pread, + .ko_pwrite = pwrite, +}; +#endif diff --git a/sbin/fsck_lfs/kernelops.h b/sbin/fsck_lfs/kernelops.h new file mode 100644 index 000000000000..f7eea13adf86 --- /dev/null +++ b/sbin/fsck_lfs/kernelops.h @@ -0,0 +1,22 @@ +#ifndef _LFS_KERNEL_OPS_H_ +#define _LFS_KERNEL_OPS_H_ + +#include +#include + +#include +#include + +struct kernelops { + int (*ko_open)(const char *, int, mode_t); + int (*ko_statvfs)(const char *, struct statvfs *, int); + int (*ko_fcntl)(int, int, void *); + int (*ko_fhopen)(const void *, size_t, int); + int (*ko_close)(int); + + ssize_t (*ko_pread)(int, void *, size_t, off_t); + ssize_t (*ko_pwrite)(int, const void *, size_t, off_t); +}; +extern struct kernelops kops; + +#endif /* _LFS_KERNEL_OPS_H_ */ diff --git a/sbin/fsck_lfs/lfs.c b/sbin/fsck_lfs/lfs.c index 9ab797dd1812..0ad9f002d1e3 100644 --- a/sbin/fsck_lfs/lfs.c +++ b/sbin/fsck_lfs/lfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: lfs.c,v 1.30 2009/02/22 20:28:05 ad Exp $ */ +/* $NetBSD: lfs.c,v 1.31 2009/08/06 00:51:55 pooka Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. * All rights reserved. @@ -90,6 +90,7 @@ #include "vnode.h" #include "lfs_user.h" #include "segwrite.h" +#include "kernelops.h" #define panic call_panic @@ -117,12 +118,12 @@ lfs_vop_strategy(struct ubuf * bp) int count; if (bp->b_flags & B_READ) { - count = pread(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, + count = kops.ko_pread(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, dbtob(bp->b_blkno)); if (count == bp->b_bcount) bp->b_flags |= B_DONE; } else { - count = pwrite(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, + count = kops.ko_pwrite(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, dbtob(bp->b_blkno)); if (count == 0) { perror("pwrite"); diff --git a/sbin/fsck_lfs/vnode.c b/sbin/fsck_lfs/vnode.c index 01a61330e71b..342f2c0e11d5 100644 --- a/sbin/fsck_lfs/vnode.c +++ b/sbin/fsck_lfs/vnode.c @@ -1,4 +1,4 @@ -/* $NetBSD: vnode.c,v 1.9 2008/04/28 20:23:08 martin Exp $ */ +/* $NetBSD: vnode.c,v 1.10 2009/08/06 00:51:55 pooka Exp $ */ /*- * Copyright (c) 2003 The NetBSD Foundation, Inc. * All rights reserved. @@ -53,6 +53,7 @@ #include "bufcache.h" #include "vnode.h" +#include "kernelops.h" struct uvnodelst vnodelist; struct uvnodelst getvnodelist[VNODE_HASH_MAX]; @@ -73,10 +74,10 @@ int raw_vop_strategy(struct ubuf * bp) { if (bp->b_flags & B_READ) { - return pread(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, + return kops.ko_pread(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, dbtob(bp->b_blkno)); } else { - return pwrite(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, + return kops.ko_pwrite(bp->b_vp->v_fd, bp->b_data, bp->b_bcount, dbtob(bp->b_blkno)); } } diff --git a/sbin/newfs_lfs/Makefile b/sbin/newfs_lfs/Makefile index 7b0ed14a68c5..221cad3a7dd3 100644 --- a/sbin/newfs_lfs/Makefile +++ b/sbin/newfs_lfs/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.8 2009/06/05 21:52:31 haad Exp $ +# $NetBSD: Makefile,v 1.9 2009/08/06 00:51:55 pooka Exp $ # @(#)Makefile 8.1 (Berkeley) 6/18/93 WARNS?= 3 # XXX: sign-compare issues @@ -8,6 +8,7 @@ WARNS?= 3 # XXX: sign-compare issues PROG= newfs_lfs SRCS= dkcksum.c make_lfs.c lfs_cksum.c misc.c newfs.c SRCS+= bufcache.c vnode.c lfs.c segwrite.c lfs_itimes.c partutil.c +SRCS+= kernelops.c MAN= newfs_lfs.8 DISKLABEL= ${NETBSDSRCDIR}/sbin/disklabel