diff --git a/sys/conf/files b/sys/conf/files index 0ac514c41abf..f6604ea4905a 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,1816 +1,1816 @@ # $FreeBSD$ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and # dependency lines other than the first are silently ignored. # acpi_quirks.h optional acpi \ dependency "$S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ compile-with "${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ no-obj no-implicit-rule before-depend \ clean "acpi_quirks.h" aicasm optional ahc \ dependency "$S/dev/aic7xxx/aicasm/*.[chyl]" \ compile-with "CC=${CC} ${MAKE} -f $S/dev/aic7xxx/aicasm/Makefile MAKESRCPATH=$S/dev/aic7xxx/aicasm" \ no-obj no-implicit-rule \ clean "aicasm* y.tab.h" aicasm optional ahd \ dependency "$S/dev/aic7xxx/aicasm/*.[chyl]" \ compile-with "CC=${CC} ${MAKE} -f $S/dev/aic7xxx/aicasm/Makefile MAKESRCPATH=$S/dev/aic7xxx/aicasm" \ no-obj no-implicit-rule \ clean "aicasm* y.tab.h" aic7xxx_seq.h optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic7xxx_seq.h" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg.h optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic7xxx_reg.h" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg_print.c optional ahc \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic7xxx_seq.h -r aic7xxx_reg.h -p aic7xxx_reg_print.c -i $S/dev/aic7xxx/aic7xxx_osm.h $S/dev/aic7xxx/aic7xxx.seq" \ no-obj no-implicit-rule local \ clean "aic7xxx_reg_print.c" \ dependency "$S/dev/aic7xxx/aic7xxx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic7xxx_reg_print.o optional ahc ahc_reg_pretty_print \ compile-with "${NORMAL_C}" \ no-implicit-rule local aic79xx_seq.h optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic79xx_seq.h" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg.h optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule before-depend local \ clean "aic79xx_reg.h" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg_print.c optional ahd pci \ compile-with "./aicasm ${INCLUDES} -I$S/cam/scsi -I$S/dev/aic7xxx -o aic79xx_seq.h -r aic79xx_reg.h -p aic79xx_reg_print.c -i $S/dev/aic7xxx/aic79xx_osm.h $S/dev/aic7xxx/aic79xx.seq" \ no-obj no-implicit-rule local \ clean "aic79xx_reg_print.c" \ dependency "$S/dev/aic7xxx/aic79xx.{reg,seq} $S/cam/scsi/scsi_message.h aicasm" aic79xx_reg_print.o optional ahd pci ahd_reg_pretty_print \ compile-with "${NORMAL_C}" \ no-implicit-rule local emu10k1-alsa%diked.h optional snd_emu10k1 pci \ dependency "$S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/emu10k1-alsa.h" \ compile-with "CC=${CC} AWK=${AWK} sh $S/tools/emu10k1-mkalsa.sh $S/gnu/dev/sound/pci/emu10k1-alsa.h emu10k1-alsa%diked.h" \ no-obj no-implicit-rule before-depend \ clean "emu10k1-alsa%diked.h" miidevs.h optional miibus \ dependency "$S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ compile-with "${AWK} -f $S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ no-obj no-implicit-rule before-depend \ clean "miidevs.h" pccarddevs.h standard \ dependency "$S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ compile-with "${AWK} -f $S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ no-obj no-implicit-rule before-depend \ clean "pccarddevs.h" usbdevs.h optional usb \ dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -h" \ no-obj no-implicit-rule before-depend \ clean "usbdevs.h" usbdevs_data.h optional usb \ dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -d" \ no-obj no-implicit-rule before-depend \ clean "usbdevs_data.h" cam/cam.c optional scbus cam/cam_periph.c optional scbus cam/cam_queue.c optional scbus cam/cam_sim.c optional scbus cam/cam_xpt.c optional scbus cam/scsi/scsi_all.c optional scbus cam/scsi/scsi_cd.c optional cd cam/scsi/scsi_ch.c optional ch cam/scsi/scsi_da.c optional da cam/scsi/scsi_low.c optional ct cam/scsi/scsi_low.c optional ncv cam/scsi/scsi_low.c optional nsp cam/scsi/scsi_low.c optional stg cam/scsi/scsi_low_pisa.c optional ct cam/scsi/scsi_low_pisa.c optional ncv cam/scsi/scsi_low_pisa.c optional nsp cam/scsi/scsi_low_pisa.c optional stg cam/scsi/scsi_pass.c optional pass cam/scsi/scsi_pt.c optional pt cam/scsi/scsi_sa.c optional sa cam/scsi/scsi_ses.c optional ses cam/scsi/scsi_targ_bh.c optional targbh cam/scsi/scsi_target.c optional targ coda/coda_fbsd.c optional vcoda coda/coda_namecache.c optional vcoda coda/coda_psdev.c optional vcoda coda/coda_subr.c optional vcoda coda/coda_venus.c optional vcoda coda/coda_vfsops.c optional vcoda coda/coda_vnops.c optional vcoda compat/linprocfs/linprocfs.c optional linprocfs contrib/altq/altq/altq_cbq.c optional altq contrib/altq/altq/altq_cdnr.c optional altq contrib/altq/altq/altq_hfsc.c optional altq contrib/altq/altq/altq_priq.c optional altq contrib/altq/altq/altq_red.c optional altq contrib/altq/altq/altq_rio.c optional altq contrib/altq/altq/altq_rmclass.c optional altq contrib/altq/altq/altq_subr.c optional altq contrib/dev/acpica/dbcmds.c optional acpi acpi_debug contrib/dev/acpica/dbdisply.c optional acpi acpi_debug contrib/dev/acpica/dbexec.c optional acpi acpi_debug contrib/dev/acpica/dbfileio.c optional acpi acpi_debug contrib/dev/acpica/dbhistry.c optional acpi acpi_debug contrib/dev/acpica/dbinput.c optional acpi acpi_debug contrib/dev/acpica/dbstats.c optional acpi acpi_debug contrib/dev/acpica/dbutils.c optional acpi acpi_debug contrib/dev/acpica/dbxface.c optional acpi acpi_debug contrib/dev/acpica/dmbuffer.c optional acpi acpi_debug contrib/dev/acpica/dmnames.c optional acpi acpi_debug contrib/dev/acpica/dmopcode.c optional acpi acpi_debug contrib/dev/acpica/dmobject.c optional acpi acpi_debug contrib/dev/acpica/dmresrc.c optional acpi acpi_debug contrib/dev/acpica/dmresrcl.c optional acpi acpi_debug contrib/dev/acpica/dmresrcs.c optional acpi acpi_debug contrib/dev/acpica/dmutils.c optional acpi acpi_debug contrib/dev/acpica/dmwalk.c optional acpi acpi_debug contrib/dev/acpica/dsfield.c optional acpi contrib/dev/acpica/dsinit.c optional acpi contrib/dev/acpica/dsmethod.c optional acpi contrib/dev/acpica/dsmthdat.c optional acpi contrib/dev/acpica/dsobject.c optional acpi contrib/dev/acpica/dsopcode.c optional acpi contrib/dev/acpica/dsutils.c optional acpi contrib/dev/acpica/dswexec.c optional acpi contrib/dev/acpica/dswload.c optional acpi contrib/dev/acpica/dswscope.c optional acpi contrib/dev/acpica/dswstate.c optional acpi contrib/dev/acpica/evevent.c optional acpi contrib/dev/acpica/evgpe.c optional acpi contrib/dev/acpica/evgpeblk.c optional acpi contrib/dev/acpica/evmisc.c optional acpi contrib/dev/acpica/evregion.c optional acpi contrib/dev/acpica/evrgnini.c optional acpi contrib/dev/acpica/evsci.c optional acpi contrib/dev/acpica/evxface.c optional acpi contrib/dev/acpica/evxfevnt.c optional acpi contrib/dev/acpica/evxfregn.c optional acpi contrib/dev/acpica/exconfig.c optional acpi contrib/dev/acpica/exconvrt.c optional acpi contrib/dev/acpica/excreate.c optional acpi contrib/dev/acpica/exdump.c optional acpi contrib/dev/acpica/exfield.c optional acpi contrib/dev/acpica/exfldio.c optional acpi contrib/dev/acpica/exmisc.c optional acpi contrib/dev/acpica/exmutex.c optional acpi contrib/dev/acpica/exnames.c optional acpi contrib/dev/acpica/exoparg1.c optional acpi contrib/dev/acpica/exoparg2.c optional acpi contrib/dev/acpica/exoparg3.c optional acpi contrib/dev/acpica/exoparg6.c optional acpi contrib/dev/acpica/exprep.c optional acpi contrib/dev/acpica/exregion.c optional acpi contrib/dev/acpica/exresnte.c optional acpi contrib/dev/acpica/exresolv.c optional acpi contrib/dev/acpica/exresop.c optional acpi contrib/dev/acpica/exstore.c optional acpi contrib/dev/acpica/exstoren.c optional acpi contrib/dev/acpica/exstorob.c optional acpi contrib/dev/acpica/exsystem.c optional acpi contrib/dev/acpica/exutils.c optional acpi contrib/dev/acpica/hwacpi.c optional acpi contrib/dev/acpica/hwgpe.c optional acpi contrib/dev/acpica/hwregs.c optional acpi contrib/dev/acpica/hwsleep.c optional acpi contrib/dev/acpica/hwtimer.c optional acpi contrib/dev/acpica/nsaccess.c optional acpi contrib/dev/acpica/nsalloc.c optional acpi contrib/dev/acpica/nsdump.c optional acpi contrib/dev/acpica/nseval.c optional acpi contrib/dev/acpica/nsinit.c optional acpi contrib/dev/acpica/nsload.c optional acpi contrib/dev/acpica/nsnames.c optional acpi contrib/dev/acpica/nsobject.c optional acpi contrib/dev/acpica/nsparse.c optional acpi contrib/dev/acpica/nssearch.c optional acpi contrib/dev/acpica/nsutils.c optional acpi contrib/dev/acpica/nswalk.c optional acpi contrib/dev/acpica/nsxfeval.c optional acpi contrib/dev/acpica/nsxfname.c optional acpi contrib/dev/acpica/nsxfobj.c optional acpi contrib/dev/acpica/psargs.c optional acpi contrib/dev/acpica/psopcode.c optional acpi contrib/dev/acpica/psparse.c optional acpi contrib/dev/acpica/psscope.c optional acpi contrib/dev/acpica/pstree.c optional acpi contrib/dev/acpica/psutils.c optional acpi contrib/dev/acpica/pswalk.c optional acpi contrib/dev/acpica/psxface.c optional acpi contrib/dev/acpica/rsaddr.c optional acpi contrib/dev/acpica/rscalc.c optional acpi contrib/dev/acpica/rscreate.c optional acpi contrib/dev/acpica/rsdump.c optional acpi contrib/dev/acpica/rsio.c optional acpi contrib/dev/acpica/rsirq.c optional acpi contrib/dev/acpica/rslist.c optional acpi contrib/dev/acpica/rsmemory.c optional acpi contrib/dev/acpica/rsmisc.c optional acpi contrib/dev/acpica/rsutils.c optional acpi contrib/dev/acpica/rsxface.c optional acpi contrib/dev/acpica/tbconvrt.c optional acpi contrib/dev/acpica/tbget.c optional acpi contrib/dev/acpica/tbgetall.c optional acpi contrib/dev/acpica/tbinstal.c optional acpi contrib/dev/acpica/tbrsdt.c optional acpi contrib/dev/acpica/tbutils.c optional acpi contrib/dev/acpica/tbxface.c optional acpi contrib/dev/acpica/tbxfroot.c optional acpi contrib/dev/acpica/utalloc.c optional acpi contrib/dev/acpica/utclib.c optional acpi contrib/dev/acpica/utcopy.c optional acpi contrib/dev/acpica/utdebug.c optional acpi contrib/dev/acpica/utdelete.c optional acpi contrib/dev/acpica/uteval.c optional acpi contrib/dev/acpica/utglobal.c optional acpi contrib/dev/acpica/utinit.c optional acpi contrib/dev/acpica/utmath.c optional acpi contrib/dev/acpica/utmisc.c optional acpi contrib/dev/acpica/utobject.c optional acpi contrib/dev/acpica/utxface.c optional acpi contrib/dev/ath/freebsd/ah_osdep.c optional ath_hal contrib/ipfilter/netinet/fil.c optional ipfilter inet contrib/ipfilter/netinet/ip_auth.c optional ipfilter inet contrib/ipfilter/netinet/ip_fil_freebsd.c optional ipfilter inet contrib/ipfilter/netinet/ip_frag.c optional ipfilter inet contrib/ipfilter/netinet/ip_log.c optional ipfilter inet contrib/ipfilter/netinet/ip_nat.c optional ipfilter inet contrib/ipfilter/netinet/ip_proxy.c optional ipfilter inet contrib/ipfilter/netinet/ip_state.c optional ipfilter inet contrib/ipfilter/netinet/ip_lookup.c optional ipfilter inet contrib/ipfilter/netinet/ip_pool.c optional ipfilter inet contrib/ipfilter/netinet/ip_htable.c optional ipfilter inet contrib/ipfilter/netinet/ip_sync.c optional ipfilter inet contrib/ipfilter/netinet/mlfk_ipl.c optional ipfilter inet contrib/ngatm/netnatm/api/cc_conn.c optional ngatm_ccatm contrib/ngatm/netnatm/api/cc_data.c optional ngatm_ccatm contrib/ngatm/netnatm/api/cc_dump.c optional ngatm_ccatm contrib/ngatm/netnatm/api/cc_port.c optional ngatm_ccatm contrib/ngatm/netnatm/api/cc_sig.c optional ngatm_ccatm contrib/ngatm/netnatm/api/cc_user.c optional ngatm_ccatm contrib/ngatm/netnatm/api/unisap.c optional ngatm_ccatm contrib/ngatm/netnatm/misc/straddr.c optional ngatm_atmbase contrib/ngatm/netnatm/misc/unimsg_common.c optional ngatm_atmbase contrib/ngatm/netnatm/msg/traffic.c optional ngatm_atmbase contrib/ngatm/netnatm/msg/uni_ie.c optional ngatm_atmbase contrib/ngatm/netnatm/msg/uni_msg.c optional ngatm_atmbase contrib/ngatm/netnatm/saal/saal_sscfu.c optional ngatm_sscfu contrib/ngatm/netnatm/saal/saal_sscop.c optional ngatm_sscop contrib/ngatm/netnatm/sig/sig_call.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_coord.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_party.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_print.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_reset.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_uni.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_unimsgcpy.c optional ngatm_uni contrib/ngatm/netnatm/sig/sig_verify.c optional ngatm_uni contrib/pf/net/if_pflog.c optional pflog contrib/pf/net/if_pfsync.c optional pfsync contrib/pf/net/pf.c optional pf contrib/pf/net/pf_if.c optional pf contrib/pf/net/pf_subr.c optional pf contrib/pf/net/pf_ioctl.c optional pf contrib/pf/net/pf_norm.c optional pf contrib/pf/net/pf_table.c optional pf contrib/pf/net/pf_osfp.c optional pf contrib/pf/netinet/in4_cksum.c optional pf inet crypto/blowfish/bf_ecb.c optional ipsec ipsec_esp crypto/blowfish/bf_skey.c optional crypto crypto/blowfish/bf_skey.c optional ipsec ipsec_esp crypto/des/des_ecb.c optional crypto crypto/des/des_ecb.c optional ipsec ipsec_esp crypto/des/des_ecb.c optional netsmbcrypto crypto/des/des_setkey.c optional crypto crypto/des/des_setkey.c optional ipsec ipsec_esp crypto/des/des_setkey.c optional netsmbcrypto crypto/rc4/rc4.c optional netgraph_mppc_encryption crypto/rijndael/rijndael-alg-fst.c optional crypto crypto/rijndael/rijndael-alg-fst.c optional geom_bde crypto/rijndael/rijndael-alg-fst.c optional ipsec crypto/rijndael/rijndael-alg-fst.c optional random crypto/rijndael/rijndael-alg-fst.c optional wlan_ccmp crypto/rijndael/rijndael-api-fst.c optional geom_bde crypto/rijndael/rijndael-api-fst.c optional random crypto/rijndael/rijndael-api.c optional crypto crypto/rijndael/rijndael-api.c optional ipsec crypto/rijndael/rijndael-api.c optional wlan_ccmp crypto/sha1.c optional carp crypto/sha1.c optional netgraph_mppc_encryption crypto/sha1.c optional crypto crypto/sha1.c optional ipsec crypto/sha2/sha2.c optional crypto crypto/sha2/sha2.c optional geom_bde crypto/sha2/sha2.c optional ipsec crypto/sha2/sha2.c optional random ddb/db_access.c optional ddb ddb/db_break.c optional ddb ddb/db_command.c optional ddb ddb/db_examine.c optional ddb ddb/db_expr.c optional ddb ddb/db_input.c optional ddb ddb/db_lex.c optional ddb ddb/db_main.c optional ddb ddb/db_output.c optional ddb ddb/db_print.c optional ddb ddb/db_ps.c optional ddb ddb/db_run.c optional ddb ddb/db_sym.c optional ddb ddb/db_thread.c optional ddb ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb #dev/dpt/dpt_control.c optional dpt dev/aac/aac.c optional aac dev/aac/aac_cam.c optional aacp aac dev/aac/aac_debug.c optional aac dev/aac/aac_disk.c optional aac dev/aac/aac_linux.c optional aac compat_linux dev/aac/aac_pci.c optional aac pci dev/acpi_support/acpi_asus.c optional acpi_asus acpi dev/acpi_support/acpi_fujitsu.c optional acpi_fujitsu acpi dev/acpi_support/acpi_ibm.c optional acpi_ibm acpi dev/acpi_support/acpi_panasonic.c optional acpi_panasonic acpi dev/acpi_support/acpi_sony.c optional acpi_sony acpi dev/acpi_support/acpi_toshiba.c optional acpi_toshiba acpi dev/acpica/Osd/OsdDebug.c optional acpi dev/acpica/Osd/OsdHardware.c optional acpi dev/acpica/Osd/OsdInterrupt.c optional acpi dev/acpica/Osd/OsdMemory.c optional acpi dev/acpica/Osd/OsdSchedule.c optional acpi dev/acpica/Osd/OsdStream.c optional acpi dev/acpica/Osd/OsdSynch.c optional acpi dev/acpica/Osd/OsdTable.c optional acpi dev/acpica/acpi.c optional acpi dev/acpica/acpi_acad.c optional acpi dev/acpica/acpi_battery.c optional acpi dev/acpica/acpi_button.c optional acpi dev/acpica/acpi_cmbat.c optional acpi dev/acpica/acpi_cpu.c optional acpi dev/acpica/acpi_ec.c optional acpi dev/acpica/acpi_isab.c optional acpi isa dev/acpica/acpi_lid.c optional acpi dev/acpica/acpi_package.c optional acpi dev/acpica/acpi_pci.c optional acpi pci dev/acpica/acpi_pci_link.c optional acpi pci dev/acpica/acpi_pcib.c optional acpi pci dev/acpica/acpi_pcib_acpi.c optional acpi pci dev/acpica/acpi_pcib_pci.c optional acpi pci dev/acpica/acpi_perf.c optional acpi dev/acpica/acpi_powerres.c optional acpi dev/acpica/acpi_quirk.c optional acpi dev/acpica/acpi_resource.c optional acpi dev/acpica/acpi_thermal.c optional acpi dev/acpica/acpi_throttle.c optional acpi dev/acpica/acpi_timer.c optional acpi dev/acpica/acpi_video.c optional acpi_video acpi dev/adlink/adlink.c optional adlink dev/advansys/adv_eisa.c optional adv eisa dev/advansys/adv_pci.c optional adv pci dev/advansys/advansys.c optional adv dev/advansys/advlib.c optional adv dev/advansys/advmcode.c optional adv dev/advansys/adw_pci.c optional adw pci dev/advansys/adwcam.c optional adw dev/advansys/adwlib.c optional adw dev/advansys/adwmcode.c optional adw dev/aha/aha.c optional aha dev/aha/aha_isa.c optional aha isa dev/aha/aha_mca.c optional aha mca dev/ahb/ahb.c optional ahb eisa dev/aic/aic.c optional aic dev/aic/aic_pccard.c optional aic pccard dev/aic7xxx/ahc_eisa.c optional ahc eisa dev/aic7xxx/ahc_isa.c optional ahc isa dev/aic7xxx/ahc_pci.c optional ahc pci dev/aic7xxx/ahd_pci.c optional ahd pci dev/aic7xxx/aic7770.c optional ahc dev/aic7xxx/aic79xx.c optional ahd pci dev/aic7xxx/aic79xx_osm.c optional ahd pci dev/aic7xxx/aic79xx_pci.c optional ahd pci dev/aic7xxx/aic7xxx.c optional ahc dev/aic7xxx/aic7xxx_93cx6.c optional ahc dev/aic7xxx/aic7xxx_osm.c optional ahc dev/aic7xxx/aic7xxx_pci.c optional ahc pci dev/amd/amd.c optional amd dev/amr/amr.c optional amr dev/amr/amr_cam.c optional amr dev/amr/amr_disk.c optional amr dev/amr/amr_pci.c optional amr pci dev/an/if_an.c optional an dev/an/if_an_isa.c optional an isa dev/an/if_an_pccard.c optional an pccard dev/an/if_an_pci.c optional an pci dev/asr/asr.c optional asr pci dev/ata/ata_if.m optional ata dev/ata/ata-all.c optional ata dev/ata/ata-card.c optional ata pccard dev/ata/ata-cbus.c optional ata pc98 dev/ata/ata-chipset.c optional ata pci dev/ata/ata-disk.c optional atadisk dev/ata/ata-dma.c optional ata pci dev/ata/ata-isa.c optional ata isa dev/ata/ata-lowlevel.c optional ata dev/ata/ata-pci.c optional ata pci dev/ata/ata-queue.c optional ata dev/ata/ata-raid.c optional ataraid dev/ata/atapi-cam.c optional atapicam dev/ata/atapi-cd.c optional atapicd dev/ata/atapi-fd.c optional atapifd dev/ata/atapi-tape.c optional atapist dev/ath/ath_rate/amrr/amrr.c optional ath_rate_amrr dev/ath/ath_rate/onoe/onoe.c optional ath_rate_onoe dev/ath/ath_rate/sample/sample.c optional ath_rate_sample dev/ath/if_ath.c optional ath dev/ath/if_ath_pci.c optional ath pci dev/awi/am79c930.c optional awi dev/awi/awi.c optional awi dev/awi/if_awi_pccard.c optional awi pccard dev/bfe/if_bfe.c optional bfe dev/bge/if_bge.c optional bge dev/bktr/bktr_audio.c optional bktr pci dev/bktr/bktr_card.c optional bktr pci dev/bktr/bktr_core.c optional bktr pci dev/bktr/bktr_i2c.c optional bktr pci smbus dev/bktr/bktr_os.c optional bktr pci dev/bktr/bktr_tuner.c optional bktr pci dev/bktr/msp34xx.c optional bktr pci dev/buslogic/bt.c optional bt dev/buslogic/bt_eisa.c optional bt eisa dev/buslogic/bt_isa.c optional bt isa dev/buslogic/bt_mca.c optional bt mca dev/buslogic/bt_pci.c optional bt pci dev/cardbus/cardbus.c optional cardbus dev/cardbus/cardbus_cis.c optional cardbus dev/ciss/ciss.c optional ciss dev/cm/smc90cx6.c optional cm dev/cnw/if_cnw.c optional cnw pccard dev/cpufreq/ichss.c optional cpufreq dev/cs/if_cs.c optional cs dev/cs/if_cs_isa.c optional cs isa dev/cs/if_cs_pccard.c optional cs pccard dev/cy/cy.c optional cy dev/cy/cy_isa.c optional cy isa dev/cy/cy_pci.c optional cy pci dev/dcons/dcons.c optional dcons dev/dcons/dcons_crom.c optional dcons_crom dev/dcons/dcons_os.c optional dcons dev/digi/CX.c optional digi_CX dev/digi/CX_PCI.c optional digi_CX_PCI dev/digi/EPCX.c optional digi_EPCX dev/digi/EPCX_PCI.c optional digi_EPCX_PCI dev/digi/Xe.c optional digi_Xe dev/digi/Xem.c optional digi_Xem dev/digi/Xr.c optional digi_Xr dev/digi/digi.c optional digi dev/digi/digi_isa.c optional digi isa dev/digi/digi_pci.c optional digi pci dev/dpt/dpt_eisa.c optional dpt eisa dev/dpt/dpt_pci.c optional dpt pci dev/dpt/dpt_scsi.c optional dpt dev/drm/ati_pcigart.c optional drm dev/drm/drm_agpsupport.c optional drm dev/drm/drm_auth.c optional drm dev/drm/drm_bufs.c optional drm dev/drm/drm_context.c optional drm dev/drm/drm_dma.c optional drm dev/drm/drm_drawable.c optional drm dev/drm/drm_drv.c optional drm dev/drm/drm_fops.c optional drm dev/drm/drm_ioctl.c optional drm dev/drm/drm_irq.c optional drm dev/drm/drm_lock.c optional drm dev/drm/drm_memory.c optional drm dev/drm/drm_pci.c optional drm dev/drm/drm_scatter.c optional drm dev/drm/drm_sysctl.c optional drm dev/drm/drm_vm.c optional drm dev/drm/mach64_dma.c optional mach64drm dev/drm/mach64_drv.c optional mach64drm dev/drm/mach64_irq.c optional mach64drm dev/drm/mach64_state.c optional mach64drm dev/drm/mga_dma.c optional mgadrm dev/drm/mga_drv.c optional mgadrm dev/drm/mga_irq.c optional mgadrm dev/drm/mga_state.c optional mgadrm \ compile-with "${NORMAL_C} -finline-limit=13500" dev/drm/mga_warp.c optional mgadrm dev/drm/r128_cce.c optional r128drm dev/drm/r128_drv.c optional r128drm dev/drm/r128_irq.c optional r128drm dev/drm/r128_state.c optional r128drm \ compile-with "${NORMAL_C} -finline-limit=13500" dev/drm/radeon_cp.c optional radeondrm dev/drm/radeon_drv.c optional radeondrm dev/drm/radeon_irq.c optional radeondrm dev/drm/radeon_mem.c optional radeondrm dev/drm/radeon_state.c optional radeondrm dev/drm/sis_drv.c optional sisdrm dev/drm/sis_ds.c optional sisdrm dev/drm/sis_mm.c optional sisdrm dev/drm/tdfx_drv.c optional tdfxdrm dev/ed/if_ed.c optional ed dev/ed/if_ed_novell.c optional ed dev/ed/if_ed_pccard.c optional ed pccard dev/ed/if_ed_pci.c optional ed pci dev/eisa/eisa_if.m standard dev/eisa/eisaconf.c optional eisa dev/em/if_em.c optional em dev/em/if_em_hw.c optional em dev/en/if_en_pci.c optional en pci dev/en/midway.c optional en dev/ep/if_ep.c optional ep dev/ep/if_ep_eisa.c optional ep eisa dev/ep/if_ep_isa.c optional ep isa dev/ep/if_ep_mca.c optional ep mca dev/ep/if_ep_pccard.c optional ep pccard dev/esp/ncr53c9x.c optional esp dev/ex/if_ex.c optional ex dev/ex/if_ex_isa.c optional ex isa #dev/ex/if_ex_pccard.c optional ex pccard dev/exca/exca.c optional cbb dev/fatm/if_fatm.c optional fatm pci dev/fe/if_fe.c optional fe dev/fe/if_fe_pccard.c optional fe pccard dev/firewire/firewire.c optional firewire dev/firewire/fwcrom.c optional firewire dev/firewire/fwdev.c optional firewire dev/firewire/fwdma.c optional firewire dev/firewire/fwmem.c optional firewire dev/firewire/fwohci.c optional firewire dev/firewire/fwohci_pci.c optional firewire pci dev/firewire/if_fwe.c optional fwe dev/firewire/if_fwip.c optional fwip dev/firewire/sbp.c optional sbp dev/firewire/sbp_targ.c optional sbp_targ dev/fxp/if_fxp.c optional fxp dev/gem/if_gem.c optional gem dev/gem/if_gem_pci.c optional gem pci dev/harp/if_harp.c optional harp pci dev/hatm/if_hatm.c optional hatm pci dev/hatm/if_hatm_intr.c optional hatm pci dev/hatm/if_hatm_ioctl.c optional hatm pci dev/hatm/if_hatm_rx.c optional hatm pci dev/hatm/if_hatm_tx.c optional hatm pci dev/hfa/fore_buffer.c optional hfa dev/hfa/fore_command.c optional hfa dev/hfa/fore_globals.c optional hfa dev/hfa/fore_if.c optional hfa dev/hfa/fore_init.c optional hfa dev/hfa/fore_intr.c optional hfa dev/hfa/fore_output.c optional hfa dev/hfa/fore_receive.c optional hfa dev/hfa/fore_stats.c optional hfa dev/hfa/fore_timer.c optional hfa dev/hfa/fore_transmit.c optional hfa dev/hfa/fore_vcm.c optional hfa #dev/hfa/hfa_eisa.c optional hfa eisa dev/hfa/hfa_freebsd.c optional hfa dev/hfa/hfa_pci.c optional hfa pci #dev/hfa/hfa_sbus.c optional hfa sbus dev/hifn/hifn7751.c optional hifn dev/hme/if_hme.c optional hme dev/hme/if_hme_pci.c optional hme pci dev/hme/if_hme_sbus.c optional hme sbus dev/ichsmb/ichsmb.c optional ichsmb dev/ichsmb/ichsmb_pci.c optional ichsmb pci dev/ida/ida.c optional ida dev/ida/ida_disk.c optional ida dev/ida/ida_eisa.c optional ida eisa dev/ida/ida_pci.c optional ida pci dev/ie/if_ie.c optional ie isa nowerror dev/ie/if_ie_isa.c optional ie isa dev/ieee488/ibfoo.c optional pcii dev/ieee488/pcii.c optional pcii dev/ieee488/upd7210.c optional pcii dev/iicbus/if_ic.c optional ic dev/iicbus/iic.c optional iic dev/iicbus/iicbb.c optional iicbb dev/iicbus/iicbb_if.m optional iicbb dev/iicbus/iicbus.c optional iicbus dev/iicbus/iicbus_if.m optional iicbus dev/iicbus/iiconf.c optional iicbus dev/iicbus/iicsmb.c optional iicsmb \ dependency "iicbus_if.h" dev/iir/iir.c optional iir dev/iir/iir_ctrl.c optional iir dev/iir/iir_pci.c optional iir pci dev/ips/ips.c optional ips dev/ips/ips_commands.c optional ips dev/ips/ips_disk.c optional ips dev/ips/ips_ioctl.c optional ips dev/ips/ips_pci.c optional ips pci dev/ipw/if_ipw.c optional ipw dev/isp/isp.c optional isp dev/isp/isp_freebsd.c optional isp dev/isp/isp_pci.c optional isp pci dev/isp/isp_sbus.c optional isp sbus dev/isp/isp_target.c optional isp dev/ispfw/ispfw.c optional ispfw dev/iwi/if_iwi.c optional iwi dev/ixgb/if_ixgb.c optional ixgb dev/ixgb/ixgb_ee.c optional ixgb dev/ixgb/ixgb_hw.c optional ixgb dev/joy/joy.c optional joy dev/joy/joy_isa.c optional joy isa dev/joy/joy_pccard.c optional joy pccard dev/led/led.c standard dev/lge/if_lge.c optional lge dev/lnc/if_lnc.c optional lnc dev/lnc/if_lnc_pci.c optional lnc pci dev/mc146818/mc146818.c optional mc146818 dev/mca/mca_bus.c optional mca dev/mcd/mcd.c optional mcd isa nowerror dev/mcd/mcd_isa.c optional mcd isa nowerror dev/md/md.c optional md dev/mem/memdev.c optional mem dev/mii/acphy.c optional miibus dev/mii/amphy.c optional miibus dev/mii/bmtphy.c optional miibus dev/mii/brgphy.c optional miibus dev/mii/ciphy.c optional miibus dev/mii/dcphy.c optional miibus pci dev/mii/e1000phy.c optional miibus dev/mii/exphy.c optional miibus dev/mii/inphy.c optional miibus dev/mii/lxtphy.c optional miibus dev/mii/mii.c optional miibus dev/mii/mii_physubr.c optional miibus dev/mii/miibus_if.m optional miibus dev/mii/mlphy.c optional miibus dev/mii/nsgphy.c optional miibus dev/mii/nsphy.c optional miibus dev/mii/pnaphy.c optional miibus dev/mii/pnphy.c optional miibus dev/mii/qsphy.c optional miibus dev/mii/rgephy.c optional miibus dev/mii/rlphy.c optional miibus dev/mii/ruephy.c optional miibus dev/mii/tdkphy.c optional miibus dev/mii/tlphy.c optional miibus dev/mii/ukphy.c optional miibus dev/mii/ukphy_subr.c optional miibus dev/mii/xmphy.c optional miibus dev/mk48txx/mk48txx.c optional mk48txx dev/mlx/mlx.c optional mlx dev/mlx/mlx_disk.c optional mlx dev/mlx/mlx_pci.c optional mlx pci dev/mly/mly.c optional mly dev/mpt/mpt.c optional mpt dev/mpt/mpt_debug.c optional mpt dev/mpt/mpt_freebsd.c optional mpt dev/mpt/mpt_pci.c optional mpt pci dev/my/if_my.c optional my dev/ncv/ncr53c500.c optional ncv dev/ncv/ncr53c500_pccard.c optional ncv pccard dev/nge/if_nge.c optional nge dev/nmdm/nmdm.c optional nmdm dev/nsp/nsp.c optional nsp dev/nsp/nsp_pccard.c optional nsp pccard dev/null/null.c standard dev/patm/if_patm.c optional patm pci dev/patm/if_patm_attach.c optional patm pci dev/patm/if_patm_intr.c optional patm pci dev/patm/if_patm_ioctl.c optional patm pci dev/patm/if_patm_rtables.c optional patm pci dev/patm/if_patm_rx.c optional patm pci dev/patm/if_patm_tx.c optional patm pci dev/pbio/pbio.c optional pbio isa dev/pccard/card_if.m standard dev/pccard/pccard.c optional pccard dev/pccard/pccard_cis.c optional pccard dev/pccard/pccard_cis_quirks.c optional pccard dev/pccard/power_if.m standard dev/pccbb/pccbb.c optional cbb dev/pccbb/pccbb_isa.c optional cbb isa dev/pccbb/pccbb_pci.c optional cbb pci dev/pci/eisa_pci.c optional pci eisa dev/pci/fixup_pci.c optional pci dev/pci/ignore_pci.c optional pci dev/pci/isa_pci.c optional pci isa dev/pci/pci.c optional pci dev/pci/pci_if.m standard dev/pci/pci_pci.c optional pci dev/pci/pci_user.c optional pci dev/pci/pcib_if.m standard dev/pdq/if_fea.c optional fea eisa dev/pdq/if_fpa.c optional fpa pci dev/pdq/pdq.c optional fea eisa nowerror dev/pdq/pdq.c optional fpa pci nowerror dev/pdq/pdq_ifsubr.c optional fea eisa nowerror dev/pdq/pdq_ifsubr.c optional fpa pci nowerror dev/ppbus/if_plip.c optional plip dev/ppbus/immio.c optional vpo dev/ppbus/lpbb.c optional lpbb dev/ppbus/lpt.c optional lpt dev/ppbus/pcfclock.c optional pcfclock dev/ppbus/ppb_1284.c optional ppbus dev/ppbus/ppb_base.c optional ppbus dev/ppbus/ppb_msq.c optional ppbus dev/ppbus/ppbconf.c optional ppbus dev/ppbus/ppbus_if.m optional ppbus dev/ppbus/ppi.c optional ppi dev/ppbus/pps.c optional pps dev/ppbus/vpo.c optional vpo dev/ppbus/vpoio.c optional vpo dev/pst/pst-iop.c optional pst dev/pst/pst-pci.c optional pst pci dev/pst/pst-raid.c optional pst dev/puc/puc.c optional puc dev/puc/puc_ebus.c optional puc ebus dev/puc/puc_pccard.c optional puc pccard dev/puc/puc_pci.c optional puc pci dev/puc/puc_sbus.c optional puc fhc dev/puc/puc_sbus.c optional puc sbus dev/puc/pucdata.c optional puc pci dev/ral/if_ral.c optional ral dev/ral/if_ralrate.c optional ral dev/ral/if_ral_pccard.c optional ral pccard dev/ral/if_ral_pci.c optional ral pci dev/random/harvest.c standard dev/random/hash.c optional random dev/random/probe.c optional random dev/random/randomdev.c optional random dev/random/randomdev_soft.c optional random dev/random/yarrow.c optional random dev/ray/if_ray.c optional ray pccard dev/rc/rc.c optional rc dev/re/if_re.c optional re dev/rndtest/rndtest.c optional rndtest dev/rp/rp.c optional rp dev/rp/rp_isa.c optional rp isa dev/rp/rp_pci.c optional rp pci dev/sab/sab.c optional sab ebus dev/safe/safe.c optional safe dev/sbsh/if_sbsh.c optional sbsh dev/scd/scd.c optional scd isa dev/scd/scd_isa.c optional scd isa dev/si/si.c optional si dev/si/si2_z280.c optional si dev/si/si3_t225.c optional si dev/si/si_eisa.c optional si eisa dev/si/si_isa.c optional si isa dev/si/si_pci.c optional si pci dev/sio/sio_pccard.c optional sio pccard dev/sio/sio_pci.c optional sio pci dev/sio/sio_puc.c optional sio puc pci dev/smbus/smb.c optional smb dev/smbus/smbconf.c optional smbus dev/smbus/smbus.c optional smbus dev/smbus/smbus_if.m optional smbus dev/sn/if_sn.c optional sn dev/sn/if_sn_isa.c optional sn isa dev/sn/if_sn_pccard.c optional sn pccard dev/snp/snp.c optional snp dev/sound/isa/ad1816.c optional snd_ad1816 isa dev/sound/isa/es1888.c optional snd_ess isa dev/sound/isa/ess.c optional snd_ess isa dev/sound/isa/gusc.c optional snd_gusc isa dev/sound/isa/mss.c optional snd_mss isa dev/sound/isa/sb16.c optional snd_sb16 isa dev/sound/isa/sb8.c optional snd_sb8 isa dev/sound/isa/sbc.c optional snd_sbc isa dev/sound/isa/sndbuf_dma.c optional sound isa dev/sound/pci/als4000.c optional snd_als4000 pci #dev/sound/pci/au88x0.c optional snd_au88x0 pci dev/sound/pci/cmi.c optional snd_cmi pci dev/sound/pci/cs4281.c optional snd_cs4281 pci dev/sound/pci/csa.c optional snd_csa pci dev/sound/pci/csapcm.c optional snd_csa pci dev/sound/pci/ds1.c optional snd_ds1 pci dev/sound/pci/emu10k1.c optional snd_emu10k1 pci \ dependency "emu10k1-alsa%diked.h" dev/sound/pci/es137x.c optional snd_es137x pci dev/sound/pci/fm801.c optional snd_fm801 pci dev/sound/pci/ich.c optional snd_ich pci dev/sound/pci/maestro.c optional snd_maestro pci dev/sound/pci/maestro3.c optional snd_maestro3 pci dev/sound/pci/neomagic.c optional snd_neomagic pci dev/sound/pci/solo.c optional snd_solo pci dev/sound/pci/t4dwave.c optional snd_t4dwave pci dev/sound/pci/via8233.c optional snd_via8233 pci dev/sound/pci/via82c686.c optional snd_via82c686 pci dev/sound/pci/vibes.c optional snd_vibes pci #dev/sound/pci/vortex1.c optional snd_vortex1 pci dev/sound/pcm/ac97.c optional sound dev/sound/pcm/ac97_if.m optional sound dev/sound/pcm/ac97_patch.c optional sound dev/sound/pcm/buffer.c optional sound dev/sound/pcm/channel.c optional sound dev/sound/pcm/channel_if.m optional sound dev/sound/pcm/dsp.c optional sound dev/sound/pcm/fake.c optional sound dev/sound/pcm/feeder.c optional sound dev/sound/pcm/feeder_fmt.c optional sound dev/sound/pcm/feeder_if.m optional sound dev/sound/pcm/feeder_rate.c optional sound dev/sound/pcm/mixer.c optional sound dev/sound/pcm/mixer_if.m optional sound dev/sound/pcm/sndstat.c optional sound dev/sound/pcm/sound.c optional sound dev/sound/pcm/vchan.c optional sound #dev/sound/usb/upcm.c optional snd_upcm usb dev/sound/usb/uaudio.c optional snd_uaudio usb dev/sound/usb/uaudio_pcm.c optional snd_uaudio usb dev/sr/if_sr.c optional sr dev/sr/if_sr_pci.c optional sr pci dev/stg/tmc18c30.c optional stg dev/stg/tmc18c30_isa.c optional stg isa dev/stg/tmc18c30_pccard.c optional stg pccard dev/stg/tmc18c30_pci.c optional stg pci dev/stg/tmc18c30_subr.c optional stg dev/streams/streams.c optional streams dev/sx/sx.c optional sx #dev/sx/sx_isa.c optional sx isa dev/sx/sx_util.c optional sx dev/sx/sx_pci.c optional sx pci dev/sym/sym_hipd.c optional sym \ dependency "$S/dev/sym/sym_{conf,defs}.h" dev/syscons/blank/blank_saver.c optional blank_saver dev/syscons/daemon/daemon_saver.c optional daemon_saver dev/syscons/dragon/dragon_saver.c optional dragon_saver dev/syscons/fade/fade_saver.c optional fade_saver dev/syscons/fire/fire_saver.c optional fire_saver dev/syscons/green/green_saver.c optional green_saver dev/syscons/logo/logo.c optional logo_saver dev/syscons/logo/logo_saver.c optional logo_saver dev/syscons/rain/rain_saver.c optional rain_saver dev/syscons/snake/snake_saver.c optional snake_saver dev/syscons/star/star_saver.c optional star_saver dev/syscons/warp/warp_saver.c optional warp_saver dev/tdfx/tdfx_pci.c optional tdfx pci dev/trm/trm.c optional trm dev/twa/tw_cl_fwimg.c optional twa dev/twa/tw_cl_init.c optional twa dev/twa/tw_cl_intr.c optional twa dev/twa/tw_cl_io.c optional twa dev/twa/tw_cl_misc.c optional twa dev/twa/tw_osl_cam.c optional twa dev/twa/tw_osl_freebsd.c optional twa dev/twe/twe.c optional twe dev/twe/twe_freebsd.c optional twe dev/tx/if_tx.c optional tx dev/txp/if_txp.c optional txp dev/uart/uart_bus_acpi.c optional uart acpi #dev/uart/uart_bus_cbus.c optional uart cbus dev/uart/uart_bus_ebus.c optional uart ebus dev/uart/uart_bus_isa.c optional uart isa dev/uart/uart_bus_pccard.c optional uart pccard dev/uart/uart_bus_pci.c optional uart pci dev/uart/uart_bus_puc.c optional uart puc dev/uart/uart_core.c optional uart dev/uart/uart_dbg.c optional uart gdb dev/uart/uart_dev_ns8250.c optional uart dev/uart/uart_dev_sab82532.c optional uart dev/uart/uart_dev_z8530.c optional uart dev/uart/uart_if.m optional uart dev/uart/uart_subr.c optional uart dev/uart/uart_tty.c optional uart dev/ubsec/ubsec.c optional ubsec # # USB support dev/usb/ehci.c optional ehci dev/usb/ehci_pci.c optional ehci pci dev/usb/hid.c optional usb dev/usb/if_aue.c optional aue dev/usb/if_axe.c optional axe dev/usb/if_cdce.c optional cdce dev/usb/if_cue.c optional cue dev/usb/if_kue.c optional kue dev/usb/if_ural.c optional ural dev/usb/if_rue.c optional rue dev/usb/if_udav.c optional udav dev/usb/ohci.c optional ohci dev/usb/ohci_pci.c optional ohci pci dev/usb/ubsa.c optional ubsa ucom dev/usb/ubser.c optional ubser dev/usb/ucom.c optional ucom dev/usb/ucycom.c optional ucycom ucom dev/usb/udbp.c optional udbp dev/usb/ufm.c optional ufm dev/usb/uftdi.c optional uftdi ucom dev/usb/ugen.c optional ugen dev/usb/uhci.c optional uhci dev/usb/uhci_pci.c optional uhci pci dev/usb/uhid.c optional uhid dev/usb/uhub.c optional usb dev/usb/ukbd.c optional ukbd dev/usb/ulpt.c optional ulpt dev/usb/umass.c optional umass dev/usb/umct.c optional umct dev/usb/umodem.c optional umodem dev/usb/ums.c optional ums dev/usb/uplcom.c optional uplcom ucom dev/usb/urio.c optional urio dev/usb/usb.c optional usb dev/usb/usb_ethersubr.c optional usb dev/usb/usb_if.m optional usb dev/usb/usb_mem.c optional usb dev/usb/usb_quirks.c optional usb dev/usb/usb_subr.c optional usb dev/usb/usbdi.c optional usb dev/usb/usbdi_util.c optional usb dev/usb/uscanner.c optional uscanner dev/usb/uvisor.c optional uvisor ucom dev/usb/uvscom.c optional uvscom ucom dev/utopia/idtphy.c optional utopia dev/utopia/suni.c optional utopia dev/utopia/utopia.c optional utopia dev/vge/if_vge.c optional vge dev/vkbd/vkbd.c optional vkbd dev/vx/if_vx.c optional vx dev/vx/if_vx_eisa.c optional vx eisa dev/vx/if_vx_pci.c optional vx pci dev/watchdog/watchdog.c standard dev/wds/wd7000.c optional wds isa dev/wi/if_wi.c optional wi dev/wi/if_wi_pccard.c optional wi pccard dev/wi/if_wi_pci.c optional wi pci dev/wl/if_wl.c optional wl isa dev/xe/if_xe.c optional xe dev/xe/if_xe_pccard.c optional xe pccard dev/zs/zs.c optional zs fs/deadfs/dead_vnops.c standard fs/devfs/devfs_devs.c standard fs/devfs/devfs_rule.c standard fs/devfs/devfs_vfsops.c standard fs/devfs/devfs_vnops.c standard fs/fdescfs/fdesc_vfsops.c optional fdescfs fs/fdescfs/fdesc_vnops.c optional fdescfs fs/fifofs/fifo_vnops.c standard fs/hpfs/hpfs_alsubr.c optional hpfs fs/hpfs/hpfs_lookup.c optional hpfs fs/hpfs/hpfs_subr.c optional hpfs fs/hpfs/hpfs_vfsops.c optional hpfs fs/hpfs/hpfs_vnops.c optional hpfs fs/msdosfs/msdosfs_conv.c optional msdosfs fs/msdosfs/msdosfs_denode.c optional msdosfs fs/msdosfs/msdosfs_fat.c optional msdosfs fs/msdosfs/msdosfs_fileno.c optional msdosfs_large fs/msdosfs/msdosfs_iconv.c optional msdosfs_iconv fs/msdosfs/msdosfs_lookup.c optional msdosfs fs/msdosfs/msdosfs_vfsops.c optional msdosfs fs/msdosfs/msdosfs_vnops.c optional msdosfs fs/ntfs/ntfs_compr.c optional ntfs fs/ntfs/ntfs_iconv.c optional ntfs_iconv fs/ntfs/ntfs_ihash.c optional ntfs fs/ntfs/ntfs_subr.c optional ntfs fs/ntfs/ntfs_vfsops.c optional ntfs fs/ntfs/ntfs_vnops.c optional ntfs fs/nullfs/null_subr.c optional nullfs fs/nullfs/null_vfsops.c optional nullfs fs/nullfs/null_vnops.c optional nullfs fs/nwfs/nwfs_io.c optional nwfs fs/nwfs/nwfs_ioctl.c optional nwfs fs/nwfs/nwfs_node.c optional nwfs fs/nwfs/nwfs_subr.c optional nwfs fs/nwfs/nwfs_vfsops.c optional nwfs fs/nwfs/nwfs_vnops.c optional nwfs fs/portalfs/portal_vfsops.c optional portalfs fs/portalfs/portal_vnops.c optional portalfs fs/procfs/procfs.c optional procfs fs/procfs/procfs_ctl.c optional procfs fs/procfs/procfs_dbregs.c optional procfs fs/procfs/procfs_fpregs.c optional procfs fs/procfs/procfs_ioctl.c optional procfs fs/procfs/procfs_map.c optional procfs fs/procfs/procfs_mem.c optional procfs fs/procfs/procfs_note.c optional procfs fs/procfs/procfs_regs.c optional procfs fs/procfs/procfs_rlimit.c optional procfs fs/procfs/procfs_status.c optional procfs fs/procfs/procfs_type.c optional procfs fs/pseudofs/pseudofs.c optional pseudofs fs/pseudofs/pseudofs_fileno.c optional pseudofs fs/pseudofs/pseudofs_vncache.c optional pseudofs fs/pseudofs/pseudofs_vnops.c optional pseudofs fs/smbfs/smbfs_io.c optional smbfs fs/smbfs/smbfs_node.c optional smbfs fs/smbfs/smbfs_smb.c optional smbfs fs/smbfs/smbfs_subr.c optional smbfs fs/smbfs/smbfs_vfsops.c optional smbfs fs/smbfs/smbfs_vnops.c optional smbfs fs/udf/osta.c optional udf fs/udf/udf_iconv.c optional udf_iconv fs/udf/udf_vfsops.c optional udf fs/udf/udf_vnops.c optional udf fs/umapfs/umap_subr.c optional umapfs fs/umapfs/umap_vfsops.c optional umapfs fs/umapfs/umap_vnops.c optional umapfs fs/unionfs/union_subr.c optional unionfs fs/unionfs/union_vfsops.c optional unionfs fs/unionfs/union_vnops.c optional unionfs gdb/gdb_main.c optional gdb gdb/gdb_packet.c optional gdb geom/bde/g_bde.c optional geom_bde geom/bde/g_bde_crypt.c optional geom_bde geom/bde/g_bde_lock.c optional geom_bde geom/bde/g_bde_work.c optional geom_bde geom/concat/g_concat.c optional geom_concat geom/gate/g_gate.c optional geom_gate geom/geom_aes.c optional geom_aes geom/geom_apple.c optional geom_apple geom/geom_bsd.c optional geom_bsd geom/geom_bsd_enc.c optional geom_bsd geom/geom_ccd.c optional ccd geom/geom_ccd.c optional geom_ccd geom/geom_ctl.c standard geom/geom_dev.c standard geom/geom_disk.c standard geom/geom_dump.c standard geom/geom_event.c standard geom/geom_fox.c optional geom_fox geom/geom_gpt.c optional geom_gpt geom/geom_io.c standard geom/geom_kern.c standard geom/geom_mbr.c optional geom_mbr geom/geom_mbr_enc.c optional geom_mbr geom/geom_pc98.c optional geom_pc98 geom/geom_pc98_enc.c optional geom_pc98 geom/geom_slice.c standard geom/geom_subr.c standard geom/geom_sunlabel.c optional geom_sunlabel geom/geom_sunlabel_enc.c optional geom_sunlabel geom/geom_vfs.c standard geom/geom_vol_ffs.c optional geom_vol geom/label/g_label.c optional geom_label geom/label/g_label_iso9660.c optional geom_label geom/label/g_label_msdosfs.c optional geom_label geom/label/g_label_ufs.c optional geom_label geom/mirror/g_mirror.c optional geom_mirror geom/mirror/g_mirror_ctl.c optional geom_mirror geom/nop/g_nop.c optional geom_nop geom/raid3/g_raid3.c optional geom_raid3 geom/raid3/g_raid3_ctl.c optional geom_raid3 geom/shsec/g_shsec.c optional geom_shsec geom/stripe/g_stripe.c optional geom_stripe geom/uzip/g_uzip.c optional geom_uzip -gnu/ext2fs/ext2_alloc.c optional ext2fs \ +gnu/fs/ext2fs/ext2_alloc.c optional ext2fs \ warning "kernel contains GPL contaminated ext2fs filesystem" -gnu/ext2fs/ext2_balloc.c optional ext2fs -gnu/ext2fs/ext2_bmap.c optional ext2fs -gnu/ext2fs/ext2_inode.c optional ext2fs -gnu/ext2fs/ext2_inode_cnv.c optional ext2fs -gnu/ext2fs/ext2_linux_balloc.c optional ext2fs -gnu/ext2fs/ext2_linux_ialloc.c optional ext2fs -gnu/ext2fs/ext2_lookup.c optional ext2fs -gnu/ext2fs/ext2_subr.c optional ext2fs -gnu/ext2fs/ext2_vfsops.c optional ext2fs -gnu/ext2fs/ext2_vnops.c optional ext2fs +gnu/fs/ext2fs/ext2_balloc.c optional ext2fs +gnu/fs/ext2fs/ext2_bmap.c optional ext2fs +gnu/fs/ext2fs/ext2_inode.c optional ext2fs +gnu/fs/ext2fs/ext2_inode_cnv.c optional ext2fs +gnu/fs/ext2fs/ext2_linux_balloc.c optional ext2fs +gnu/fs/ext2fs/ext2_linux_ialloc.c optional ext2fs +gnu/fs/ext2fs/ext2_lookup.c optional ext2fs +gnu/fs/ext2fs/ext2_subr.c optional ext2fs +gnu/fs/ext2fs/ext2_vfsops.c optional ext2fs +gnu/fs/ext2fs/ext2_vnops.c optional ext2fs # # Support for hardware performance monitoring counters # dev/hwpmc/hwpmc_mod.c optional hwpmc dev/hwpmc/hwpmc_logging.c optional hwpmc # # isdn4bsd device drivers # i4b/driver/i4b_trace.c optional i4btrc i4b/driver/i4b_rbch.c optional i4brbch i4b/driver/i4b_tel.c optional i4btel i4b/driver/i4b_ipr.c optional i4bipr net/slcompress.c optional i4bipr i4b/driver/i4b_ctl.c optional i4bctl i4b/driver/i4b_ing.c optional i4bing i4b/driver/i4b_isppp.c optional i4bisppp net/slcompress.c optional i4bisppp # # isdn4bsd CAPI driver # i4b/capi/capi_l4if.c optional i4bcapi i4b/capi/capi_llif.c optional i4bcapi i4b/capi/capi_msgs.c optional i4bcapi # # isdn4bsd AVM B1/T1 CAPI driver # i4b/capi/iavc/iavc_pci.c optional iavc i4bcapi pci i4b/capi/iavc/iavc_isa.c optional iavc i4bcapi isa i4b/capi/iavc/iavc_lli.c optional iavc i4bcapi i4b/capi/iavc/iavc_card.c optional iavc i4bcapi # # isdn4bsd support # i4b/layer2/i4b_mbuf.c optional i4btrc # # isdn4bsd Q.921 handler # i4b/layer2/i4b_l2.c optional i4bq921 i4b/layer2/i4b_l2fsm.c optional i4bq921 i4b/layer2/i4b_uframe.c optional i4bq921 i4b/layer2/i4b_tei.c optional i4bq921 i4b/layer2/i4b_sframe.c optional i4bq921 i4b/layer2/i4b_iframe.c optional i4bq921 i4b/layer2/i4b_l2timer.c optional i4bq921 i4b/layer2/i4b_util.c optional i4bq921 i4b/layer2/i4b_lme.c optional i4bq921 # # isdn4bsd Q.931 handler # i4b/layer3/i4b_q931.c optional i4bq931 i4b/layer3/i4b_l3fsm.c optional i4bq931 i4b/layer3/i4b_l3timer.c optional i4bq931 i4b/layer3/i4b_l2if.c optional i4bq931 i4b/layer3/i4b_l4if.c optional i4bq931 i4b/layer3/i4b_q932fac.c optional i4bq931 # # isdn4bsd control device driver, interface to isdnd # i4b/layer4/i4b_i4bdrv.c optional i4b i4b/layer4/i4b_l4.c optional i4b i4b/layer4/i4b_l4mgmt.c optional i4b i4b/layer4/i4b_l4timer.c optional i4b # isa/isa_if.m standard isa/isa_common.c optional isa isa/isahint.c optional isa isa/orm.c optional isa isa/pnp.c optional isa isa/pnpparse.c optional isa isofs/cd9660/cd9660_bmap.c optional cd9660 isofs/cd9660/cd9660_lookup.c optional cd9660 isofs/cd9660/cd9660_node.c optional cd9660 isofs/cd9660/cd9660_rrip.c optional cd9660 isofs/cd9660/cd9660_util.c optional cd9660 isofs/cd9660/cd9660_vfsops.c optional cd9660 isofs/cd9660/cd9660_vnops.c optional cd9660 isofs/cd9660/cd9660_iconv.c optional cd9660_iconv kern/bus_if.m standard kern/clock_if.m optional genclock kern/cpufreq_if.m standard kern/device_if.m standard kern/imgact_elf.c standard kern/imgact_shell.c standard kern/inflate.c optional gzip kern/init_main.c standard kern/init_sysent.c standard kern/kern_acct.c standard kern/kern_acl.c standard kern/kern_alq.c optional alq kern/kern_clock.c standard kern/kern_condvar.c standard kern/kern_conf.c standard kern/kern_cpu.c standard kern/kern_context.c standard kern/kern_descrip.c standard kern/kern_environment.c standard kern/kern_event.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fork.c standard kern/kern_idle.c standard kern/kern_intr.c standard kern/kern_jail.c standard kern/kern_kse.c standard kern/kern_kthread.c standard kern/kern_ktr.c optional ktr kern/kern_ktrace.c standard kern/kern_linker.c standard kern/kern_lock.c standard kern/kern_lockf.c standard kern/kern_mac.c standard kern/kern_malloc.c standard kern/kern_mbuf.c standard kern/kern_mib.c standard kern/kern_module.c standard kern/kern_mtxpool.c standard kern/kern_mutex.c standard kern/kern_ntptime.c standard kern/kern_physio.c standard kern/kern_pmc.c standard kern/kern_poll.c optional device_polling kern/kern_proc.c standard kern/kern_prot.c standard kern/kern_resource.c standard kern/kern_sema.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard kern/kern_subr.c standard kern/kern_sx.c standard kern/kern_synch.c standard kern/kern_syscalls.c standard kern/kern_sysctl.c standard kern/kern_tc.c standard kern/kern_thr.c standard kern/kern_thread.c standard kern/kern_time.c standard kern/kern_timeout.c standard kern/kern_umtx.c standard kern/kern_uuid.c standard kern/kern_xxx.c standard kern/link_elf.c standard kern/linker_if.m standard kern/md4c.c optional netsmb kern/md5c.c standard kern/sched_4bsd.c optional sched_4bsd kern/sched_ule.c optional sched_ule kern/subr_autoconf.c standard kern/subr_blist.c standard kern/subr_bus.c standard kern/subr_clock.c optional genclock kern/subr_devstat.c standard kern/subr_disk.c standard kern/subr_eventhandler.c standard kern/subr_hints.c standard kern/subr_kdb.c standard kern/subr_kobj.c standard kern/subr_log.c standard kern/subr_mbpool.c optional libmbpool kern/subr_mchain.c optional libmchain kern/subr_module.c standard kern/subr_msgbuf.c standard kern/subr_param.c standard kern/subr_pcpu.c standard kern/subr_power.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rman.c standard kern/subr_sbuf.c standard kern/subr_scanf.c standard kern/subr_sleepqueue.c standard kern/subr_smp.c standard kern/subr_taskqueue.c standard kern/subr_trap.c standard kern/subr_turnstile.c standard kern/subr_unit.c standard kern/subr_witness.c optional witness kern/sys_generic.c standard kern/sys_pipe.c standard kern/sys_process.c standard kern/sys_socket.c standard kern/syscalls.c optional witness kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem kern/sysv_shm.c optional sysvshm kern/tty.c standard kern/tty_compat.c standard kern/tty_conf.c standard kern/tty_cons.c standard kern/tty_pty.c optional pty kern/tty_subr.c standard kern/tty_tty.c standard kern/uipc_accf.c optional inet kern/uipc_cow.c optional zero_copy_sockets kern/uipc_domain.c standard kern/uipc_mbuf.c standard kern/uipc_mbuf2.c standard kern/uipc_proto.c standard kern/uipc_sem.c optional p1003_1b_semaphores kern/uipc_socket.c standard kern/uipc_socket2.c standard kern/uipc_syscalls.c standard kern/uipc_usrreq.c standard kern/vfs_aio.c optional vfs_aio kern/vfs_bio.c standard kern/vfs_cache.c standard kern/vfs_cluster.c standard kern/vfs_default.c standard kern/vfs_export.c standard kern/vfs_hash.c standard kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_mount.c standard kern/vfs_subr.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard # # These files in libkern/ are those needed by all architectures. Some # of the files in libkern/ are only needed on some architectures, e.g., # libkern/divdi3.c is needed by i386 but not alpha. Also, some of these # routines may be optimized for a particular platform. In either case, # the file should be moved to conf/files. from here. # libkern/arc4random.c standard libkern/bcd.c standard libkern/bsearch.c standard libkern/crc32.c standard libkern/fnmatch.c standard libkern/gets.c standard libkern/iconv.c optional libiconv libkern/iconv_converter_if.m optional libiconv libkern/iconv_xlat.c optional libiconv libkern/iconv_xlat16.c optional libiconv libkern/index.c standard libkern/inet_ntoa.c standard libkern/mcount.c optional profiling-routine libkern/qsort.c standard libkern/qsort_r.c standard libkern/random.c standard libkern/rindex.c standard libkern/scanc.c standard libkern/skpc.c standard libkern/strcat.c standard libkern/strcmp.c standard libkern/strcpy.c standard libkern/strdup.c standard libkern/strlcat.c standard libkern/strlcpy.c standard libkern/strlen.c standard libkern/strncmp.c standard libkern/strncpy.c standard libkern/strsep.c standard libkern/strspn.c standard libkern/strtol.c standard libkern/strtoq.c standard libkern/strtoul.c standard libkern/strtouq.c standard libkern/strvalid.c standard net/bpf.c standard net/bpf_filter.c optional bpf net/bpf_filter.c optional netgraph_bpf net/bridge.c optional bridge net/bridgestp.c optional if_bridge net/bsd_comp.c optional ppp_bsdcomp net/if.c standard net/if_arcsubr.c optional arcnet net/if_atmsubr.c optional atm net/if_bridge.c optional if_bridge net/if_clone.c standard net/if_disc.c optional disc net/if_ef.c optional ef net/if_ethersubr.c optional ether net/if_faith.c optional faith net/if_fddisubr.c optional fddi net/if_fwsubr.c optional fwip net/if_gif.c optional gif net/if_gre.c optional gre net/if_iso88025subr.c optional token net/if_loop.c optional loop net/if_media.c standard net/if_mib.c standard net/if_ppp.c optional ppp net/if_sl.c optional sl net/if_spppfr.c optional sppp net/if_spppfr.c optional i4bisppp net/if_spppsubr.c optional sppp net/if_spppsubr.c optional i4bisppp net/if_stf.c optional stf net/if_tun.c optional tun net/if_tap.c optional tap net/if_vlan.c optional vlan net/netisr.c standard net/ppp_deflate.c optional ppp_deflate net/ppp_tty.c optional ppp net/pfil.c optional ether net/pfil.c optional inet net/radix.c standard net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rtsock.c standard net/slcompress.c optional netgraph_vjc net/slcompress.c optional ppp net/slcompress.c optional sl net/slcompress.c optional sppp net/zlib.c optional ppp_deflate net/zlib.c optional ipsec net/zlib.c optional crypto net/zlib.c optional geom_uzip net80211/ieee80211.c optional wlan net80211/ieee80211_acl.c optional wlan_acl net80211/ieee80211_crypto.c optional wlan net80211/ieee80211_crypto_ccmp.c optional wlan_ccmp net80211/ieee80211_crypto_none.c optional wlan net80211/ieee80211_crypto_tkip.c optional wlan_tkip net80211/ieee80211_crypto_wep.c optional wlan_wep net80211/ieee80211_freebsd.c optional wlan net80211/ieee80211_input.c optional wlan net80211/ieee80211_ioctl.c optional wlan net80211/ieee80211_node.c optional wlan net80211/ieee80211_output.c optional wlan net80211/ieee80211_proto.c optional wlan net80211/ieee80211_xauth.c optional wlan_xauth netatalk/aarp.c optional netatalk netatalk/at_control.c optional netatalk netatalk/at_proto.c optional netatalk netatalk/at_rmx.c optional netatalkdebug netatalk/ddp_input.c optional netatalk netatalk/ddp_output.c optional netatalk netatalk/ddp_pcb.c optional netatalk netatalk/ddp_usrreq.c optional netatalk netatm/atm_aal5.c optional atm_core netatm/atm_cm.c optional atm_core netatm/atm_device.c optional atm_core netatm/atm_if.c optional atm_core netatm/atm_proto.c optional atm_core netatm/atm_signal.c optional atm_core netatm/atm_socket.c optional atm_core netatm/atm_subr.c optional atm_core netatm/atm_usrreq.c optional atm_core netatm/ipatm/ipatm_event.c optional atm_ip atm_core netatm/ipatm/ipatm_if.c optional atm_ip atm_core netatm/ipatm/ipatm_input.c optional atm_ip atm_core netatm/ipatm/ipatm_load.c optional atm_ip atm_core netatm/ipatm/ipatm_output.c optional atm_ip atm_core netatm/ipatm/ipatm_usrreq.c optional atm_ip atm_core netatm/ipatm/ipatm_vcm.c optional atm_ip atm_core netatm/sigpvc/sigpvc_if.c optional atm_sigpvc atm_core netatm/sigpvc/sigpvc_subr.c optional atm_sigpvc atm_core netatm/spans/spans_arp.c optional atm_spans atm_core \ dependency "spans_xdr.h" netatm/spans/spans_cls.c optional atm_spans atm_core netatm/spans/spans_if.c optional atm_spans atm_core netatm/spans/spans_kxdr.c optional atm_spans atm_core netatm/spans/spans_msg.c optional atm_spans atm_core netatm/spans/spans_print.c optional atm_spans atm_core netatm/spans/spans_proto.c optional atm_spans atm_core netatm/spans/spans_subr.c optional atm_spans atm_core netatm/spans/spans_util.c optional atm_spans atm_core spans_xdr.h optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -h -C $S/netatm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.h" \ clean "spans_xdr.h" \ no-obj no-implicit-rule spans_xdr.c optional atm_spans atm_core \ before-depend \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "rpcgen -c -C $S/netatm/spans/spans_xdr.x | grep -v rpc/rpc.h > spans_xdr.c" \ clean "spans_xdr.c" \ no-obj no-implicit-rule local spans_xdr.o optional atm_spans atm_core \ dependency "$S/netatm/spans/spans_xdr.x" \ compile-with "${NORMAL_C}" \ no-implicit-rule local netatm/uni/q2110_sigaa.c optional atm_uni atm_core netatm/uni/q2110_sigcpcs.c optional atm_uni atm_core netatm/uni/q2110_subr.c optional atm_uni atm_core netatm/uni/qsaal1_sigaa.c optional atm_uni atm_core netatm/uni/qsaal1_sigcpcs.c optional atm_uni atm_core netatm/uni/qsaal1_subr.c optional atm_uni atm_core netatm/uni/sscf_uni.c optional atm_uni atm_core netatm/uni/sscf_uni_lower.c optional atm_uni atm_core netatm/uni/sscf_uni_upper.c optional atm_uni atm_core netatm/uni/sscop.c optional atm_uni atm_core netatm/uni/sscop_lower.c optional atm_uni atm_core netatm/uni/sscop_pdu.c optional atm_uni atm_core netatm/uni/sscop_sigaa.c optional atm_uni atm_core netatm/uni/sscop_sigcpcs.c optional atm_uni atm_core netatm/uni/sscop_subr.c optional atm_uni atm_core netatm/uni/sscop_timer.c optional atm_uni atm_core netatm/uni/sscop_upper.c optional atm_uni atm_core netatm/uni/uni_load.c optional atm_uni atm_core netatm/uni/uniarp.c optional atm_uni atm_core netatm/uni/uniarp_cache.c optional atm_uni atm_core netatm/uni/uniarp_input.c optional atm_uni atm_core netatm/uni/uniarp_output.c optional atm_uni atm_core netatm/uni/uniarp_timer.c optional atm_uni atm_core netatm/uni/uniarp_vcm.c optional atm_uni atm_core netatm/uni/uniip.c optional atm_uni atm_core netatm/uni/unisig_decode.c optional atm_uni atm_core netatm/uni/unisig_encode.c optional atm_uni atm_core netatm/uni/unisig_if.c optional atm_uni atm_core netatm/uni/unisig_mbuf.c optional atm_uni atm_core netatm/uni/unisig_msg.c optional atm_uni atm_core netatm/uni/unisig_print.c optional atm_uni atm_core netatm/uni/unisig_proto.c optional atm_uni atm_core netatm/uni/unisig_sigmgr_state.c optional atm_uni atm_core netatm/uni/unisig_subr.c optional atm_uni atm_core netatm/uni/unisig_util.c optional atm_uni atm_core netatm/uni/unisig_vc_state.c optional atm_uni atm_core netgraph/atm/atmpif/ng_atmpif.c optional netgraph_atm_atmpif netgraph/atm/atmpif/ng_atmpif_harp.c optional netgraph_atm_atmpif netgraph/atm/ccatm/ng_ccatm.c optional ngatm_ccatm netgraph/atm/ng_atm.c optional ngatm_atm netgraph/atm/ngatmbase.c optional ngatm_atmbase netgraph/atm/sscfu/ng_sscfu.c optional ngatm_sscfu netgraph/atm/sscop/ng_sscop.c optional ngatm_sscop netgraph/atm/uni/ng_uni.c optional ngatm_uni netgraph/bluetooth/common/ng_bluetooth.c optional netgraph_bluetooth netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c optional netgraph_bluetooth_bt3c netgraph/bluetooth/drivers/h4/ng_h4.c optional netgraph_bluetooth_h4 netgraph/bluetooth/drivers/ubt/ng_ubt.c optional netgraph_bluetooth_ubt netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c optional netgraph_bluetooth_ubtbcmfw netgraph/bluetooth/hci/ng_hci_cmds.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_evnt.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_main.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_misc.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_ulpi.c optional netgraph_bluetooth_hci netgraph/bluetooth/l2cap/ng_l2cap_cmds.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_evnt.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_llpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_main.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_misc.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_ulpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/socket/ng_btsocket.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_hci_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_rfcomm.c optional netgraph_bluetooth_socket netgraph/netflow/netflow.c optional netgraph_netflow netgraph/netflow/ng_netflow.c optional netgraph_netflow netgraph/ng_UI.c optional netgraph_UI netgraph/ng_async.c optional netgraph_async netgraph/ng_atmllc.c optional netgraph_atmllc netgraph/ng_base.c optional netgraph netgraph/ng_bpf.c optional netgraph_bpf netgraph/ng_bridge.c optional netgraph_bridge netgraph/ng_cisco.c optional netgraph_cisco netgraph/ng_device.c optional netgraph_device netgraph/ng_echo.c optional netgraph_echo netgraph/ng_eiface.c optional netgraph_eiface netgraph/ng_ether.c optional netgraph_ether netgraph/ng_fec.c optional netgraph_fec netgraph/ng_frame_relay.c optional netgraph_frame_relay netgraph/ng_gif.c optional netgraph_gif netgraph/ng_gif_demux.c optional netgraph_gif_demux netgraph/ng_hole.c optional netgraph_hole netgraph/ng_iface.c optional netgraph_iface netgraph/ng_ip_input.c optional netgraph_ip_input netgraph/ng_ipfw.c optional netgraph_ipfw netgraph/ng_ksocket.c optional netgraph_ksocket netgraph/ng_l2tp.c optional netgraph_l2tp netgraph/ng_lmi.c optional netgraph_lmi netgraph/ng_mppc.c optional netgraph_mppc_compression netgraph/ng_mppc.c optional netgraph_mppc_encryption netgraph/ng_nat.c optional netgraph_nat netgraph/ng_one2many.c optional netgraph_one2many netgraph/ng_parse.c optional netgraph netgraph/ng_ppp.c optional netgraph_ppp netgraph/ng_pppoe.c optional netgraph_pppoe netgraph/ng_pptpgre.c optional netgraph_pptpgre netgraph/ng_rfc1490.c optional netgraph_rfc1490 netgraph/ng_socket.c optional netgraph_socket netgraph/ng_split.c optional netgraph_split netgraph/ng_sppp.c optional netgraph_sppp netgraph/ng_tcpmss.c optional netgraph_tcpmss netgraph/ng_tee.c optional netgraph_tee netgraph/ng_tty.c optional netgraph_tty netgraph/ng_vjc.c optional netgraph_vjc netinet/accf_data.c optional accept_filter_data netinet/accf_http.c optional accept_filter_http netinet/if_atm.c optional atm netinet/if_ether.c optional ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/ip_carp.c optional carp netinet/in_gif.c optional gif inet netinet/ip_gre.c optional gre inet netinet/ip_id.c optional inet netinet/in_pcb.c optional inet netinet/in_proto.c optional inet netinet/in_rmx.c optional inet netinet/ip_divert.c optional ipdivert netinet/ip_dummynet.c optional dummynet netinet/ip_ecn.c optional inet netinet/ip_ecn.c optional inet6 netinet/ip_encap.c optional inet netinet/ip_encap.c optional inet6 netinet/ip_fastfwd.c optional inet netinet/ip_fw2.c optional ipfirewall netinet/ip_fw_pfil.c optional ipfirewall netinet/ip_icmp.c optional inet netinet/ip_input.c optional inet netinet/ip_mroute.c optional mrouting netinet/ip_output.c optional inet netinet/raw_ip.c optional inet netinet/tcp_debug.c optional tcpdebug netinet/tcp_hostcache.c optional inet netinet/tcp_input.c optional inet netinet/tcp_output.c optional inet netinet/tcp_sack.c optional inet netinet/tcp_subr.c optional inet netinet/tcp_syncache.c optional inet netinet/tcp_timer.c optional inet netinet/tcp_usrreq.c optional inet netinet/udp_usrreq.c optional inet netinet/libalias/alias.c optional libalias netinet/libalias/alias_cuseeme.c optional libalias netinet/libalias/alias_db.c optional libalias netinet/libalias/alias_ftp.c optional libalias netinet/libalias/alias_irc.c optional libalias netinet/libalias/alias_nbt.c optional libalias netinet/libalias/alias_old.c optional libalias netinet/libalias/alias_pptp.c optional libalias netinet/libalias/alias_proxy.c optional libalias netinet/libalias/alias_skinny.c optional libalias netinet/libalias/alias_skinny.c optional libalias netinet/libalias/alias_smedia.c optional libalias netinet/libalias/alias_util.c optional libalias netinet6/ah_aesxcbcmac.c optional ipsec netinet6/ah_core.c optional ipsec netinet6/ah_input.c optional ipsec netinet6/ah_output.c optional ipsec netinet6/dest6.c optional inet6 netinet6/esp_aesctr.c optional ipsec ipsec_esp netinet6/esp_core.c optional ipsec ipsec_esp netinet6/esp_input.c optional ipsec ipsec_esp netinet6/esp_output.c optional ipsec ipsec_esp netinet6/esp_rijndael.c optional ipsec ipsec_esp netinet6/frag6.c optional inet6 netinet6/icmp6.c optional inet6 netinet6/in6.c optional inet6 netinet6/in6_cksum.c optional inet6 netinet6/in6_gif.c optional gif inet6 netinet6/in6_ifattach.c optional inet6 netinet6/in6_pcb.c optional inet6 netinet6/in6_proto.c optional inet6 netinet6/in6_rmx.c optional inet6 netinet6/in6_src.c optional inet6 netinet6/ip6_forward.c optional inet6 netinet6/ip6_fw.c optional inet6 ipv6firewall netinet6/ip6_id.c optional inet6 netinet6/ip6_input.c optional inet6 netinet6/ip6_mroute.c optional inet6 netinet6/ip6_output.c optional inet6 netinet6/ipcomp_core.c optional ipsec netinet6/ipcomp_input.c optional ipsec netinet6/ipcomp_output.c optional ipsec netinet6/ipsec.c optional ipsec netinet6/mld6.c optional inet6 netinet6/nd6.c optional inet6 netinet6/nd6_nbr.c optional inet6 netinet6/nd6_rtr.c optional inet6 netinet6/raw_ip6.c optional inet6 netinet6/route6.c optional inet6 netinet6/scope6.c optional inet6 netinet6/udp6_output.c optional inet6 netinet6/udp6_usrreq.c optional inet6 netipsec/ipsec.c optional fast_ipsec netipsec/ipsec_input.c optional fast_ipsec netipsec/ipsec_mbuf.c optional fast_ipsec netipsec/ipsec_output.c optional fast_ipsec netipsec/key.c optional fast_ipsec netipsec/key_debug.c optional fast_ipsec netipsec/keysock.c optional fast_ipsec netipsec/xform_ah.c optional fast_ipsec netipsec/xform_esp.c optional fast_ipsec netipsec/xform_ipcomp.c optional fast_ipsec netipsec/xform_ipip.c optional fast_ipsec netipsec/xform_tcp.c optional fast_ipsec tcp_signature netipx/ipx.c optional ipx netipx/ipx_cksum.c optional ipx netipx/ipx_input.c optional ipx netipx/ipx_ip.c optional ipx netipx/ipx_outputfl.c optional ipx netipx/ipx_pcb.c optional ipx netipx/ipx_proto.c optional ipx netipx/ipx_usrreq.c optional ipx netipx/spx_debug.c optional ipx netipx/spx_usrreq.c optional ipx netkey/key.c optional ipsec netkey/key_debug.c optional ipsec netkey/keydb.c optional ipsec netkey/keysock.c optional ipsec netnatm/natm.c optional natm netnatm/natm_pcb.c optional natm netnatm/natm_proto.c optional natm netncp/ncp_conn.c optional ncp netncp/ncp_crypt.c optional ncp netncp/ncp_login.c optional ncp netncp/ncp_mod.c optional ncp netncp/ncp_ncp.c optional ncp netncp/ncp_nls.c optional ncp netncp/ncp_rq.c optional ncp netncp/ncp_sock.c optional ncp netncp/ncp_subr.c optional ncp netsmb/smb_conn.c optional netsmb netsmb/smb_crypt.c optional netsmb netsmb/smb_dev.c optional netsmb netsmb/smb_iod.c optional netsmb netsmb/smb_rq.c optional netsmb netsmb/smb_smb.c optional netsmb netsmb/smb_subr.c optional netsmb netsmb/smb_trantcp.c optional netsmb netsmb/smb_usr.c optional netsmb nfs/nfs_common.c optional nfsclient nfs/nfs_common.c optional nfsserver nfs4client/nfs4_dev.c optional nfsclient nfs4client/nfs4_idmap.c optional nfsclient nfs4client/nfs4_socket.c optional nfsclient nfs4client/nfs4_subs.c optional nfsclient nfs4client/nfs4_vfs_subs.c optional nfsclient nfs4client/nfs4_vfsops.c optional nfsclient nfs4client/nfs4_vn_subs.c optional nfsclient nfs4client/nfs4_vnops.c optional nfsclient nfsclient/bootp_subr.c optional bootp nfsclient nfsclient/krpc_subr.c optional bootp nfsclient nfsclient/nfs_bio.c optional nfsclient nfsclient/nfs_diskless.c optional nfsclient nfs_root nfsclient/nfs_node.c optional nfsclient nfsclient/nfs_socket.c optional nfsclient nfsclient/nfs_subs.c optional nfsclient nfsclient/nfs_nfsiod.c optional nfsclient nfsclient/nfs_vfsops.c optional nfsclient nfsclient/nfs_vnops.c optional nfsclient nfsclient/nfs_lock.c optional nfsclient nfsserver/nfs_serv.c optional nfsserver nfsserver/nfs_srvsock.c optional nfsserver nfsserver/nfs_srvcache.c optional nfsserver nfsserver/nfs_srvsubs.c optional nfsserver nfsserver/nfs_syscalls.c optional nfsserver # crypto support opencrypto/cast.c optional crypto opencrypto/cast.c optional ipsec ipsec_esp opencrypto/criov.c optional crypto opencrypto/crypto.c optional crypto opencrypto/cryptodev.c optional cryptodev opencrypto/cryptosoft.c optional crypto opencrypto/deflate.c optional crypto opencrypto/rmd160.c optional crypto opencrypto/rmd160.c optional ipsec opencrypto/skipjack.c optional crypto opencrypto/xform.c optional crypto pci/agp.c optional agp pci pci/agp_if.m optional agp pci pci/alpm.c optional alpm pci pci/amdpm.c optional amdpm pci pci/amdpm.c optional nfpm pci pci/if_dc.c optional dc pci pci/if_de.c optional de pci pci/if_mn.c optional mn pci pci/if_pcn.c optional pcn pci pci/if_rl.c optional rl pci pci/if_sf.c optional sf pci pci/if_sis.c optional sis pci pci/if_sk.c optional sk pci pci/if_ste.c optional ste pci pci/if_ti.c optional ti pci pci/if_tl.c optional tl pci pci/if_vr.c optional vr pci pci/if_wb.c optional wb pci pci/if_xl.c optional xl pci pci/intpm.c optional intpm pci pci/ncr.c optional ncr pci pci/viapm.c optional viapm pci pci/xrpu.c optional xrpu pci posix4/ksched.c optional _kposix_priority_scheduling posix4/p1003_1b.c standard posix4/posix4_mib.c standard rpc/rpcclnt.c optional nfsclient security/mac/mac_inet.c optional mac inet security/mac/mac_label.c optional mac security/mac/mac_net.c optional mac security/mac/mac_pipe.c optional mac security/mac/mac_posix_sem.c optional mac security/mac/mac_process.c optional mac security/mac/mac_socket.c optional mac security/mac/mac_system.c optional mac security/mac/mac_sysv_msg.c optional mac security/mac/mac_sysv_sem.c optional mac security/mac/mac_sysv_shm.c optional mac security/mac/mac_vfs.c optional mac security/mac_biba/mac_biba.c optional mac_biba security/mac_bsdextended/mac_bsdextended.c optional mac_bsdextended security/mac_ifoff/mac_ifoff.c optional mac_ifoff security/mac_lomac/mac_lomac.c optional mac_lomac security/mac_mls/mac_mls.c optional mac_mls security/mac_none/mac_none.c optional mac_none security/mac_partition/mac_partition.c optional mac_partition security/mac_portacl/mac_portacl.c optional mac_portacl security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids security/mac_stub/mac_stub.c optional mac_stub security/mac_test/mac_test.c optional mac_test ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_inode.c optional ffs ufs/ffs/ffs_snapshot.c optional ffs ufs/ffs/ffs_softdep.c optional ffs ufs/ffs/ffs_subr.c optional ffs ufs/ffs/ffs_tables.c optional ffs ufs/ffs/ffs_vfsops.c optional ffs ufs/ffs/ffs_vnops.c optional ffs ufs/ffs/ffs_rawread.c optional directio ufs/ufs/ufs_acl.c optional ffs ufs/ufs/ufs_bmap.c optional ffs ufs/ufs/ufs_dirhash.c optional ffs ufs/ufs/ufs_extattr.c optional ffs ufs/ufs/ufs_inode.c optional ffs ufs/ufs/ufs_lookup.c optional ffs ufs/ufs/ufs_quota.c optional ffs ufs/ufs/ufs_vfsops.c optional ffs ufs/ufs/ufs_vnops.c optional ffs vm/default_pager.c standard vm/device_pager.c standard vm/phys_pager.c standard vm/swap_pager.c standard vm/uma_core.c standard vm/uma_dbg.c standard vm/vm_contig.c standard vm/memguard.c optional DEBUG_MEMGUARD vm/vm_fault.c standard vm/vm_glue.c standard vm/vm_init.c standard vm/vm_kern.c standard vm/vm_map.c standard vm/vm_meter.c standard vm/vm_mmap.c standard vm/vm_object.c standard vm/vm_page.c standard vm/vm_pageout.c standard vm/vm_pageq.c standard vm/vm_pager.c standard vm/vm_unix.c standard vm/vm_zeroidle.c standard vm/vnode_pager.c standard diff --git a/sys/gnu/fs/ext2fs/ext2_alloc.c b/sys/gnu/fs/ext2fs/ext2_alloc.c index 1644861e45e5..8acfda8f1536 100644 --- a/sys/gnu/fs/ext2fs/ext2_alloc.c +++ b/sys/gnu/fs/ext2fs/ext2_alloc.c @@ -1,535 +1,535 @@ /*- * modified for Lites 1.1 * * Aug 1995, Godmar Back (gback@cs.utah.edu) * University of Utah, Department of Computer Science */ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)ffs_alloc.c 8.8 (Berkeley) 2/21/94 * $FreeBSD$ */ #include #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include static void ext2_fserr(struct ext2_sb_info *, u_int, char *); /* * Linux calls this functions at the following locations: * (1) the inode is freed * (2) a preallocation miss occurs * (3) truncate is called * (4) release_file is called and f_mode & 2 * * I call it in ext2_inactive, ext2_truncate, ext2_vfree and in (2) * the call in vfree might be redundant */ void ext2_discard_prealloc(ip) struct inode * ip; { #ifdef EXT2_PREALLOCATE if (ip->i_prealloc_count) { int i = ip->i_prealloc_count; ip->i_prealloc_count = 0; ext2_free_blocks (ITOV(ip)->v_mount, ip->i_prealloc_block, i); } #endif } /* * Allocate a block in the file system. * * this takes the framework from ffs_alloc. To implement the * actual allocation, it calls ext2_new_block, the ported version * of the same Linux routine. * * we note that this is always called in connection with ext2_blkpref * * preallocation is done as Linux does it */ int ext2_alloc(ip, lbn, bpref, size, cred, bnp) struct inode *ip; int32_t lbn, bpref; int size; struct ucred *cred; int32_t *bnp; { struct ext2_sb_info *fs; int32_t bno; *bnp = 0; fs = ip->i_e2fs; #if DIAGNOSTIC if ((u_int)size > fs->s_blocksize || blkoff(fs, size) != 0) { vn_printf(ip->i_devvp, "bsize = %lu, size = %d, fs = %s\n", fs->s_blocksize, size, fs->fs_fsmnt); panic("ext2_alloc: bad size"); } if (cred == NOCRED) panic("ext2_alloc: missing credential"); #endif /* DIAGNOSTIC */ if (size == fs->s_blocksize && fs->s_es->s_free_blocks_count == 0) goto nospace; if (cred->cr_uid != 0 && fs->s_es->s_free_blocks_count < fs->s_es->s_r_blocks_count) goto nospace; if (bpref >= fs->s_es->s_blocks_count) bpref = 0; /* call the Linux code */ #ifdef EXT2_PREALLOCATE /* To have a preallocation hit, we must * - have at least one block preallocated * - and our preferred block must have that block number or one below */ if (ip->i_prealloc_count && (bpref == ip->i_prealloc_block || bpref + 1 == ip->i_prealloc_block)) { bno = ip->i_prealloc_block++; ip->i_prealloc_count--; /* ext2_debug ("preallocation hit (%lu/%lu).\n", ++alloc_hits, ++alloc_attempts); */ /* Linux gets, clears, and releases the buffer at this point - we don't have to that; we leave it to the caller */ } else { ext2_discard_prealloc (ip); /* ext2_debug ("preallocation miss (%lu/%lu).\n", alloc_hits, ++alloc_attempts); */ if (S_ISREG(ip->i_mode)) bno = ext2_new_block (ITOV(ip)->v_mount, bpref, &ip->i_prealloc_count, &ip->i_prealloc_block); else bno = (int32_t)ext2_new_block(ITOV(ip)->v_mount, bpref, 0, 0); } #else bno = (int32_t)ext2_new_block(ITOV(ip)->v_mount, bpref, 0, 0); #endif if (bno > 0) { /* set next_alloc fields as done in block_getblk */ ip->i_next_alloc_block = lbn; ip->i_next_alloc_goal = bno; ip->i_blocks += btodb(size); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; return (0); } nospace: ext2_fserr(fs, cred->cr_uid, "file system full"); uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt); return (ENOSPC); } /* * Reallocate a sequence of blocks into a contiguous sequence of blocks. * * The vnode and an array of buffer pointers for a range of sequential * logical blocks to be made contiguous is given. The allocator attempts * to find a range of sequential blocks starting as close as possible to * an fs_rotdelay offset from the end of the allocation for the logical * block immediately preceding the current range. If successful, the * physical block numbers in the buffer pointers and in the inode are * changed to reflect the new allocation. If unsuccessful, the allocation * is left unchanged. The success in doing the reallocation is returned. * Note that the error return is not reflected back to the user. Rather * the previous block allocation will be used. */ #ifdef FANCY_REALLOC #include static int doasyncfree = 1; #ifdef OPT_DEBUG SYSCTL_INT(_debug, 14, doasyncfree, CTLFLAG_RW, &doasyncfree, 0, ""); #endif /* OPT_DEBUG */ #endif int ext2_reallocblks(ap) struct vop_reallocblks_args /* { struct vnode *a_vp; struct cluster_save *a_buflist; } */ *ap; { #ifndef FANCY_REALLOC /* printf("ext2_reallocblks not implemented\n"); */ return ENOSPC; #else struct ext2_sb_info *fs; struct inode *ip; struct vnode *vp; struct buf *sbp, *ebp; int32_t *bap, *sbap, *ebap; struct cluster_save *buflist; int32_t start_lbn, end_lbn, soff, eoff, newblk, blkno; struct indir start_ap[NIADDR + 1], end_ap[NIADDR + 1], *idp; int i, len, start_lvl, end_lvl, pref, ssize; vp = ap->a_vp; ip = VTOI(vp); fs = ip->i_e2fs; #ifdef UNKLAR if (fs->fs_contigsumsize <= 0) return (ENOSPC); #endif buflist = ap->a_buflist; len = buflist->bs_nchildren; start_lbn = buflist->bs_children[0]->b_lblkno; end_lbn = start_lbn + len - 1; #if DIAGNOSTIC for (i = 1; i < len; i++) if (buflist->bs_children[i]->b_lblkno != start_lbn + i) panic("ext2_reallocblks: non-cluster"); #endif /* * If the latest allocation is in a new cylinder group, assume that * the filesystem has decided to move and do not force it back to * the previous cylinder group. */ if (dtog(fs, dbtofsb(fs, buflist->bs_children[0]->b_blkno)) != dtog(fs, dbtofsb(fs, buflist->bs_children[len - 1]->b_blkno))) return (ENOSPC); if (ufs_getlbns(vp, start_lbn, start_ap, &start_lvl) || ufs_getlbns(vp, end_lbn, end_ap, &end_lvl)) return (ENOSPC); /* * Get the starting offset and block map for the first block. */ if (start_lvl == 0) { sbap = &ip->i_db[0]; soff = start_lbn; } else { idp = &start_ap[start_lvl - 1]; if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &sbp)) { brelse(sbp); return (ENOSPC); } sbap = (int32_t *)sbp->b_data; soff = idp->in_off; } /* * Find the preferred location for the cluster. */ pref = ext2_blkpref(ip, start_lbn, soff, sbap); /* * If the block range spans two block maps, get the second map. */ if (end_lvl == 0 || (idp = &end_ap[end_lvl - 1])->in_off + 1 >= len) { ssize = len; } else { #if DIAGNOSTIC if (start_ap[start_lvl-1].in_lbn == idp->in_lbn) panic("ext2_reallocblk: start == end"); #endif ssize = len - (idp->in_off + 1); if (bread(vp, idp->in_lbn, (int)fs->s_blocksize, NOCRED, &ebp)) goto fail; ebap = (int32_t *)ebp->b_data; } /* * Search the block map looking for an allocation of the desired size. */ if ((newblk = (int32_t)ext2_hashalloc(ip, dtog(fs, pref), (long)pref, len, (u_long (*)())ext2_clusteralloc)) == 0) goto fail; /* * We have found a new contiguous block. * * First we have to replace the old block pointers with the new * block pointers in the inode and indirect blocks associated * with the file. */ blkno = newblk; for (bap = &sbap[soff], i = 0; i < len; i++, blkno += fs->s_frags_per_block) { if (i == ssize) bap = ebap; #if DIAGNOSTIC if (buflist->bs_children[i]->b_blkno != fsbtodb(fs, *bap)) panic("ext2_reallocblks: alloc mismatch"); #endif *bap++ = blkno; } /* * Next we must write out the modified inode and indirect blocks. * For strict correctness, the writes should be synchronous since * the old block values may have been written to disk. In practise * they are almost never written, but if we are concerned about * strict correctness, the `doasyncfree' flag should be set to zero. * * The test on `doasyncfree' should be changed to test a flag * that shows whether the associated buffers and inodes have * been written. The flag should be set when the cluster is * started and cleared whenever the buffer or inode is flushed. * We can then check below to see if it is set, and do the * synchronous write only when it has been cleared. */ if (sbap != &ip->i_db[0]) { if (doasyncfree) bdwrite(sbp); else bwrite(sbp); } else { ip->i_flag |= IN_CHANGE | IN_UPDATE; if (!doasyncfree) ext2_update(vp, 1); } if (ssize < len) if (doasyncfree) bdwrite(ebp); else bwrite(ebp); /* * Last, free the old blocks and assign the new blocks to the buffers. */ for (blkno = newblk, i = 0; i < len; i++, blkno += fs->s_frags_per_block) { ext2_blkfree(ip, dbtofsb(fs, buflist->bs_children[i]->b_blkno), fs->s_blocksize); buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno); } return (0); fail: if (ssize < len) brelse(ebp); if (sbap != &ip->i_db[0]) brelse(sbp); return (ENOSPC); #endif /* FANCY_REALLOC */ } /* * Allocate an inode in the file system. * * we leave the actual allocation strategy to the (modified) * ext2_new_inode(), to make sure we get the policies right */ int ext2_valloc(pvp, mode, cred, vpp) struct vnode *pvp; int mode; struct ucred *cred; struct vnode **vpp; { struct inode *pip; struct ext2_sb_info *fs; struct inode *ip; ino_t ino; int i, error; *vpp = NULL; pip = VTOI(pvp); fs = pip->i_e2fs; if (fs->s_es->s_free_inodes_count == 0) goto noinodes; /* call the Linux routine - it returns the inode number only */ ino = ext2_new_inode(pip, mode); if (ino == 0) goto noinodes; error = VFS_VGET(pvp->v_mount, ino, LK_EXCLUSIVE, vpp); if (error) { ext2_vfree(pvp, ino, mode); return (error); } ip = VTOI(*vpp); /* the question is whether using VGET was such good idea at all - Linux doesn't read the old inode in when it's allocating a new one. I will set at least i_size & i_blocks the zero. */ ip->i_mode = 0; ip->i_size = 0; ip->i_blocks = 0; ip->i_flags = 0; /* now we want to make sure that the block pointers are zeroed out */ for (i = 0; i < NDADDR; i++) ip->i_db[i] = 0; for (i = 0; i < NIADDR; i++) ip->i_ib[i] = 0; /* * Set up a new generation number for this inode. * XXX check if this makes sense in ext2 */ if (ip->i_gen == 0 || ++ip->i_gen == 0) ip->i_gen = random() / 2 + 1; /* printf("ext2_valloc: allocated inode %d\n", ino); */ return (0); noinodes: ext2_fserr(fs, cred->cr_uid, "out of inodes"); uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); return (ENOSPC); } /* * Select the desired position for the next block in a file. * * we try to mimic what Remy does in inode_getblk/block_getblk * * we note: blocknr == 0 means that we're about to allocate either * a direct block or a pointer block at the first level of indirection * (In other words, stuff that will go in i_db[] or i_ib[]) * * blocknr != 0 means that we're allocating a block that is none * of the above. Then, blocknr tells us the number of the block * that will hold the pointer */ int32_t ext2_blkpref(ip, lbn, indx, bap, blocknr) struct inode *ip; int32_t lbn; int indx; int32_t *bap; int32_t blocknr; { int tmp; /* if the next block is actually what we thought it is, then set the goal to what we thought it should be */ if(ip->i_next_alloc_block == lbn) return ip->i_next_alloc_goal; /* now check whether we were provided with an array that basically tells us previous blocks to which we want to stay closeby */ if(bap) for (tmp = indx - 1; tmp >= 0; tmp--) if (bap[tmp]) return bap[tmp]; /* else let's fall back to the blocknr, or, if there is none, follow the rule that a block should be allocated near its inode */ return blocknr ? blocknr : (int32_t)(ip->i_block_group * EXT2_BLOCKS_PER_GROUP(ip->i_e2fs)) + ip->i_e2fs->s_es->s_first_data_block; } /* * Free a block or fragment. * * pass on to the Linux code */ void ext2_blkfree(ip, bno, size) struct inode *ip; int32_t bno; long size; { struct ext2_sb_info *fs; fs = ip->i_e2fs; /* * call Linux code with mount *, block number, count */ ext2_free_blocks(ITOV(ip)->v_mount, bno, size / fs->s_frag_size); } /* * Free an inode. * * the maintenance of the actual bitmaps is again up to the linux code */ int ext2_vfree(pvp, ino, mode) struct vnode *pvp; ino_t ino; int mode; { struct ext2_sb_info *fs; struct inode *pip; mode_t save_i_mode; pip = VTOI(pvp); fs = pip->i_e2fs; if ((u_int)ino > fs->s_inodes_per_group * fs->s_groups_count) panic("ext2_vfree: range: devvp = %p, ino = %d, fs = %s", pip->i_devvp, ino, fs->fs_fsmnt); /* ext2_debug("ext2_vfree (%d, %d) called\n", pip->i_number, mode); */ ext2_discard_prealloc(pip); /* we need to make sure that ext2_free_inode can adjust the used_dir_counts in the group summary information - I'd really like to know what the rationale behind this 'set i_mode to zero to denote an unused inode' is */ save_i_mode = pip->i_mode; pip->i_mode = mode; ext2_free_inode(pip); pip->i_mode = save_i_mode; return (0); } /* * Fserr prints the name of a file system with an error diagnostic. * * The form of the error message is: * fs: error message */ static void ext2_fserr(fs, uid, cp) struct ext2_sb_info *fs; u_int uid; char *cp; { log(LOG_ERR, "uid %d on %s: %s\n", uid, fs->fs_fsmnt, cp); } diff --git a/sys/gnu/fs/ext2fs/ext2_balloc.c b/sys/gnu/fs/ext2fs/ext2_balloc.c index a12ed351d48b..f15a9606ea68 100644 --- a/sys/gnu/fs/ext2fs/ext2_balloc.c +++ b/sys/gnu/fs/ext2fs/ext2_balloc.c @@ -1,310 +1,310 @@ /*- * modified for Lites 1.1 * * Aug 1995, Godmar Back (gback@cs.utah.edu) * University of Utah, Department of Computer Science */ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)ffs_balloc.c 8.4 (Berkeley) 9/23/93 * $FreeBSD$ */ #include #include #include #include #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* * Balloc defines the structure of file system storage * by allocating the physical blocks on a device given * the inode and the logical block number in a file. */ int ext2_balloc(ip, bn, size, cred, bpp, flags) struct inode *ip; int32_t bn; int size; struct ucred *cred; struct buf **bpp; int flags; { struct ext2_sb_info *fs; int32_t nb; struct buf *bp, *nbp; struct vnode *vp = ITOV(ip); struct indir indirs[NIADDR + 2]; int32_t newb, lbn, *bap, pref; int osize, nsize, num, i, error; /* ext2_debug("ext2_balloc called (%d, %d, %d)\n", ip->i_number, (int)bn, (int)size); */ *bpp = NULL; if (bn < 0) return (EFBIG); fs = ip->i_e2fs; lbn = bn; /* * check if this is a sequential block allocation. * If so, increment next_alloc fields to allow ext2_blkpref * to make a good guess */ if (lbn == ip->i_next_alloc_block + 1) { ip->i_next_alloc_block++; ip->i_next_alloc_goal++; } /* * The first NDADDR blocks are direct blocks */ if (bn < NDADDR) { nb = ip->i_db[bn]; /* no new block is to be allocated, and no need to expand the file */ if (nb != 0 && ip->i_size >= (bn + 1) * fs->s_blocksize) { error = bread(vp, bn, fs->s_blocksize, NOCRED, &bp); if (error) { brelse(bp); return (error); } bp->b_blkno = fsbtodb(fs, nb); *bpp = bp; return (0); } if (nb != 0) { /* * Consider need to reallocate a fragment. */ osize = fragroundup(fs, blkoff(fs, ip->i_size)); nsize = fragroundup(fs, size); if (nsize <= osize) { error = bread(vp, bn, osize, NOCRED, &bp); if (error) { brelse(bp); return (error); } bp->b_blkno = fsbtodb(fs, nb); } else { /* Godmar thinks: this shouldn't happen w/o fragments */ printf("nsize %d(%d) > osize %d(%d) nb %d\n", (int)nsize, (int)size, (int)osize, (int)ip->i_size, (int)nb); panic( "ext2_balloc: Something is terribly wrong"); /* * please note there haven't been any changes from here on - * FFS seems to work. */ } } else { if (ip->i_size < (bn + 1) * fs->s_blocksize) nsize = fragroundup(fs, size); else nsize = fs->s_blocksize; error = ext2_alloc(ip, bn, ext2_blkpref(ip, bn, (int)bn, &ip->i_db[0], 0), nsize, cred, &newb); if (error) return (error); bp = getblk(vp, bn, nsize, 0, 0, 0); bp->b_blkno = fsbtodb(fs, newb); if (flags & B_CLRBUF) vfs_bio_clrbuf(bp); } ip->i_db[bn] = dbtofsb(fs, bp->b_blkno); ip->i_flag |= IN_CHANGE | IN_UPDATE; *bpp = bp; return (0); } /* * Determine the number of levels of indirection. */ pref = 0; if ((error = ext2_getlbns(vp, bn, indirs, &num)) != 0) return(error); #if DIAGNOSTIC if (num < 1) panic ("ext2_balloc: ext2_getlbns returned indirect block"); #endif /* * Fetch the first indirect block allocating if necessary. */ --num; nb = ip->i_ib[indirs[0].in_off]; if (nb == 0) { #if 0 pref = ext2_blkpref(ip, lbn, 0, (int32_t *)0, 0); #else /* see the comment by ext2_blkpref. What we do here is to pretend that it'd be good for a block holding indirect pointers to be allocated near its predecessor in terms of indirection, or the last direct block. We shamelessly exploit the fact that i_ib immediately follows i_db. Godmar thinks it make sense to allocate i_ib[0] immediately after i_db[11], but it's not utterly clear whether this also applies to i_ib[1] and i_ib[0] */ pref = ext2_blkpref(ip, lbn, indirs[0].in_off + EXT2_NDIR_BLOCKS, &ip->i_db[0], 0); #endif if ((error = ext2_alloc(ip, lbn, pref, (int)fs->s_blocksize, cred, &newb)) != 0) return (error); nb = newb; bp = getblk(vp, indirs[1].in_lbn, fs->s_blocksize, 0, 0, 0); bp->b_blkno = fsbtodb(fs, newb); vfs_bio_clrbuf(bp); /* * Write synchronously so that indirect blocks * never point at garbage. */ if ((error = bwrite(bp)) != 0) { ext2_blkfree(ip, nb, fs->s_blocksize); return (error); } ip->i_ib[indirs[0].in_off] = newb; ip->i_flag |= IN_CHANGE | IN_UPDATE; } /* * Fetch through the indirect blocks, allocating as necessary. */ for (i = 1;;) { error = bread(vp, indirs[i].in_lbn, (int)fs->s_blocksize, NOCRED, &bp); if (error) { brelse(bp); return (error); } bap = (int32_t *)bp->b_data; nb = bap[indirs[i].in_off]; if (i == num) break; i += 1; if (nb != 0) { brelse(bp); continue; } if (pref == 0) #if 1 /* see the comment above and by ext2_blkpref * I think this implements Linux policy, but * does it really make sense to allocate to * block containing pointers together ? * Also, will it ever succeed ? */ pref = ext2_blkpref(ip, lbn, indirs[i].in_off, bap, bp->b_lblkno); #else pref = ext2_blkpref(ip, lbn, 0, (int32_t *)0, 0); #endif if ((error = ext2_alloc(ip, lbn, pref, (int)fs->s_blocksize, cred, &newb)) != 0) { brelse(bp); return (error); } nb = newb; nbp = getblk(vp, indirs[i].in_lbn, fs->s_blocksize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); vfs_bio_clrbuf(nbp); /* * Write synchronously so that indirect blocks * never point at garbage. */ if ((error = bwrite(nbp)) != 0) { ext2_blkfree(ip, nb, fs->s_blocksize); brelse(bp); return (error); } bap[indirs[i - 1].in_off] = nb; /* * If required, write synchronously, otherwise use * delayed write. */ if (flags & B_SYNC) { bwrite(bp); } else { bdwrite(bp); } } /* * Get the data block, allocating if necessary. */ if (nb == 0) { pref = ext2_blkpref(ip, lbn, indirs[i].in_off, &bap[0], bp->b_lblkno); if ((error = ext2_alloc(ip, lbn, pref, (int)fs->s_blocksize, cred, &newb)) != 0) { brelse(bp); return (error); } nb = newb; nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); if (flags & B_CLRBUF) vfs_bio_clrbuf(nbp); bap[indirs[i].in_off] = nb; /* * If required, write synchronously, otherwise use * delayed write. */ if (flags & B_SYNC) { bwrite(bp); } else { bdwrite(bp); } *bpp = nbp; return (0); } brelse(bp); if (flags & B_CLRBUF) { error = bread(vp, lbn, (int)fs->s_blocksize, NOCRED, &nbp); if (error) { brelse(nbp); return (error); } } else { nbp = getblk(vp, lbn, fs->s_blocksize, 0, 0, 0); nbp->b_blkno = fsbtodb(fs, nb); } *bpp = nbp; return (0); } diff --git a/sys/gnu/fs/ext2fs/ext2_bmap.c b/sys/gnu/fs/ext2fs/ext2_bmap.c index 54fe8b3d6828..9d5e37bf3948 100644 --- a/sys/gnu/fs/ext2fs/ext2_bmap.c +++ b/sys/gnu/fs/ext2fs/ext2_bmap.c @@ -1,335 +1,335 @@ /*- * Copyright (c) 1989, 1991, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95 * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include /* * Bmap converts a the logical block number of a file to its physical block * number on the disk. The conversion is done by using the logical block * number to index into the array of block pointers described by the dinode. */ int ext2_bmap(ap) struct vop_bmap_args /* { struct vnode *a_vp; daddr_t a_bn; struct bufobj **a_bop; daddr_t *a_bnp; int *a_runp; int *a_runb; } */ *ap; { int32_t blkno; int error; /* * Check for underlying vnode requests and ensure that logical * to physical mapping is requested. */ if (ap->a_bop != NULL) *ap->a_bop = &VTOI(ap->a_vp)->i_devvp->v_bufobj; if (ap->a_bnp == NULL) return (0); error = ext2_bmaparray(ap->a_vp, ap->a_bn, &blkno, ap->a_runp, ap->a_runb); *ap->a_bnp = blkno; return (error); } /* * Indirect blocks are now on the vnode for the file. They are given negative * logical block numbers. Indirect blocks are addressed by the negative * address of the first data block to which they point. Double indirect blocks * are addressed by one less than the address of the first indirect block to * which they point. Triple indirect blocks are addressed by one less than * the address of the first double indirect block to which they point. * * ufs_bmaparray does the bmap conversion, and if requested returns the * array of logical blocks which must be traversed to get to a block. * Each entry contains the offset into that block that gets you to the * next block and the disk address of the block (if it is assigned). */ int ext2_bmaparray(vp, bn, bnp, runp, runb) struct vnode *vp; int32_t bn; int32_t *bnp; int *runp; int *runb; { struct inode *ip; struct buf *bp; struct ext2mount *ump; struct mount *mp; struct vnode *devvp; struct indir a[NIADDR+1], *ap; int32_t daddr; long metalbn; int error, num, maxrun = 0, bsize; int *nump; ap = NULL; ip = VTOI(vp); mp = vp->v_mount; ump = VFSTOEXT2(mp); devvp = ump->um_devvp; bsize = EXT2_BLOCK_SIZE(ump->um_e2fs); if (runp) { maxrun = mp->mnt_iosize_max / bsize - 1; *runp = 0; } if (runb) { *runb = 0; } ap = a; nump = # error = ext2_getlbns(vp, bn, ap, nump); if (error) return (error); num = *nump; if (num == 0) { *bnp = blkptrtodb(ump, ip->i_db[bn]); if (*bnp == 0) { *bnp = -1; } else if (runp) { int32_t bnb = bn; for (++bn; bn < NDADDR && *runp < maxrun && is_sequential(ump, ip->i_db[bn - 1], ip->i_db[bn]); ++bn, ++*runp); bn = bnb; if (runb && (bn > 0)) { for (--bn; (bn >= 0) && (*runb < maxrun) && is_sequential(ump, ip->i_db[bn], ip->i_db[bn+1]); --bn, ++*runb); } } return (0); } /* Get disk address out of indirect block array */ daddr = ip->i_ib[ap->in_off]; for (bp = NULL, ++ap; --num; ++ap) { /* * Exit the loop if there is no disk address assigned yet and * the indirect block isn't in the cache, or if we were * looking for an indirect block and we've found it. */ metalbn = ap->in_lbn; if ((daddr == 0 && !incore(&vp->v_bufobj, metalbn)) || metalbn == bn) break; /* * If we get here, we've either got the block in the cache * or we have a disk address for it, go fetch it. */ if (bp) bqrelse(bp); ap->in_exists = 1; bp = getblk(vp, metalbn, bsize, 0, 0, 0); if ((bp->b_flags & B_CACHE) == 0) { #ifdef DIAGNOSTIC if (!daddr) panic("ufs_bmaparray: indirect block not in cache"); #endif bp->b_blkno = blkptrtodb(ump, daddr); bp->b_iocmd = BIO_READ; bp->b_flags &= ~B_INVAL; bp->b_ioflags &= ~BIO_ERROR; vfs_busy_pages(bp, 0); bp->b_iooffset = dbtob(bp->b_blkno); bstrategy(bp); curproc->p_stats->p_ru.ru_inblock++; /* XXX */ error = bufwait(bp); if (error) { brelse(bp); return (error); } } daddr = ((int32_t *)bp->b_data)[ap->in_off]; if (num == 1 && daddr && runp) { for (bn = ap->in_off + 1; bn < MNINDIR(ump) && *runp < maxrun && is_sequential(ump, ((int32_t *)bp->b_data)[bn - 1], ((int32_t *)bp->b_data)[bn]); ++bn, ++*runp); bn = ap->in_off; if (runb && bn) { for(--bn; bn >= 0 && *runb < maxrun && is_sequential(ump, ((int32_t *)bp->b_data)[bn], ((int32_t *)bp->b_data)[bn+1]); --bn, ++*runb); } } } if (bp) bqrelse(bp); /* * Since this is FFS independent code, we are out of scope for the * definitions of BLK_NOCOPY and BLK_SNAP, but we do know that they * will fall in the range 1..um_seqinc, so we use that test and * return a request for a zeroed out buffer if attempts are made * to read a BLK_NOCOPY or BLK_SNAP block. */ if ((ip->i_flags & SF_SNAPSHOT) && daddr > 0 && daddr < ump->um_seqinc){ *bnp = -1; return (0); } *bnp = blkptrtodb(ump, daddr); if (*bnp == 0) { *bnp = -1; } return (0); } /* * Create an array of logical block number/offset pairs which represent the * path of indirect blocks required to access a data block. The first "pair" * contains the logical block number of the appropriate single, double or * triple indirect block and the offset into the inode indirect block array. * Note, the logical block number of the inode single/double/triple indirect * block appears twice in the array, once with the offset into the i_ib and * once with the offset into the page itself. */ int ext2_getlbns(vp, bn, ap, nump) struct vnode *vp; int32_t bn; struct indir *ap; int *nump; { long blockcnt, metalbn, realbn; struct ext2mount *ump; int i, numlevels, off; int64_t qblockcnt; ump = VFSTOEXT2(vp->v_mount); if (nump) *nump = 0; numlevels = 0; realbn = bn; if ((long)bn < 0) bn = -(long)bn; /* The first NDADDR blocks are direct blocks. */ if (bn < NDADDR) return (0); /* * Determine the number of levels of indirection. After this loop * is done, blockcnt indicates the number of data blocks possible * at the previous level of indirection, and NIADDR - i is the number * of levels of indirection needed to locate the requested block. */ for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) { if (i == 0) return (EFBIG); /* * Use int64_t's here to avoid overflow for triple indirect * blocks when longs have 32 bits and the block size is more * than 4K. */ qblockcnt = (int64_t)blockcnt * MNINDIR(ump); if (bn < qblockcnt) break; blockcnt = qblockcnt; } /* Calculate the address of the first meta-block. */ if (realbn >= 0) metalbn = -(realbn - bn + NIADDR - i); else metalbn = -(-realbn - bn + NIADDR - i); /* * At each iteration, off is the offset into the bap array which is * an array of disk addresses at the current level of indirection. * The logical block number and the offset in that block are stored * into the argument array. */ ap->in_lbn = metalbn; ap->in_off = off = NIADDR - i; ap->in_exists = 0; ap++; for (++numlevels; i <= NIADDR; i++) { /* If searching for a meta-data block, quit when found. */ if (metalbn == realbn) break; off = (bn / blockcnt) % MNINDIR(ump); ++numlevels; ap->in_lbn = metalbn; ap->in_off = off; ap->in_exists = 0; ++ap; metalbn -= -1 + off * blockcnt; blockcnt /= MNINDIR(ump); } if (nump) *nump = numlevels; return (0); } diff --git a/sys/gnu/fs/ext2fs/ext2_inode.c b/sys/gnu/fs/ext2fs/ext2_inode.c index 46ba9d1e6b0c..8f1b21e76de4 100644 --- a/sys/gnu/fs/ext2fs/ext2_inode.c +++ b/sys/gnu/fs/ext2fs/ext2_inode.c @@ -1,536 +1,536 @@ /*- * modified for Lites 1.1 * * Aug 1995, Godmar Back (gback@cs.utah.edu) * University of Utah, Department of Computer Science */ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)ffs_inode.c 8.5 (Berkeley) 12/30/93 * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include static int ext2_indirtrunc(struct inode *, int32_t, int32_t, int32_t, int, long *); /* * Update the access, modified, and inode change times as specified by the * IN_ACCESS, IN_UPDATE, and IN_CHANGE flags respectively. Write the inode * to disk if the IN_MODIFIED flag is set (it may be set initially, or by * the timestamp update). The IN_LAZYMOD flag is set to force a write * later if not now. If we write now, then clear both IN_MODIFIED and * IN_LAZYMOD to reflect the presumably successful write, and if waitfor is * set, then wait for the write to complete. */ int ext2_update(vp, waitfor) struct vnode *vp; int waitfor; { struct ext2_sb_info *fs; struct buf *bp; struct inode *ip; int error; ext2_itimes(vp); ip = VTOI(vp); if ((ip->i_flag & IN_MODIFIED) == 0) return (0); ip->i_flag &= ~(IN_LAZYMOD | IN_MODIFIED); if (vp->v_mount->mnt_flag & MNT_RDONLY) return (0); fs = ip->i_e2fs; if ((error = bread(ip->i_devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), (int)fs->s_blocksize, NOCRED, &bp)) != 0) { brelse(bp); return (error); } ext2_i2ei(ip, (struct ext2_inode *)((char *)bp->b_data + EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number))); if (waitfor && (vp->v_mount->mnt_flag & MNT_ASYNC) == 0) return (bwrite(bp)); else { bdwrite(bp); return (0); } } #define SINGLE 0 /* index of single indirect block */ #define DOUBLE 1 /* index of double indirect block */ #define TRIPLE 2 /* index of triple indirect block */ /* * Truncate the inode oip to at most length size, freeing the * disk blocks. */ int ext2_truncate(vp, length, flags, cred, td) struct vnode *vp; off_t length; int flags; struct ucred *cred; struct thread *td; { struct vnode *ovp = vp; int32_t lastblock; struct inode *oip; int32_t bn, lbn, lastiblock[NIADDR], indir_lbn[NIADDR]; int32_t oldblks[NDADDR + NIADDR], newblks[NDADDR + NIADDR]; struct ext2_sb_info *fs; struct buf *bp; int offset, size, level; long count, nblocks, blocksreleased = 0; int aflags, error, i, allerror; off_t osize; /* printf("ext2_truncate called %d to %d\n", VTOI(ovp)->i_number, length); */ /* * negative file sizes will totally break the code below and * are not meaningful anyways. */ if (length < 0) return EFBIG; oip = VTOI(ovp); if (ovp->v_type == VLNK && oip->i_size < ovp->v_mount->mnt_maxsymlinklen) { #if DIAGNOSTIC if (length != 0) panic("ext2_truncate: partial truncate of symlink"); #endif bzero((char *)&oip->i_shortlink, (u_int)oip->i_size); oip->i_size = 0; oip->i_flag |= IN_CHANGE | IN_UPDATE; return (ext2_update(ovp, 1)); } if (oip->i_size == length) { oip->i_flag |= IN_CHANGE | IN_UPDATE; return (ext2_update(ovp, 0)); } fs = oip->i_e2fs; osize = oip->i_size; ext2_discard_prealloc(oip); /* * Lengthen the size of the file. We must ensure that the * last byte of the file is allocated. Since the smallest * value of oszie is 0, length will be at least 1. */ if (osize < length) { if (length > oip->i_e2fs->fs_maxfilesize) return (EFBIG); offset = blkoff(fs, length - 1); lbn = lblkno(fs, length - 1); aflags = B_CLRBUF; if (flags & IO_SYNC) aflags |= B_SYNC; vnode_pager_setsize(ovp, length); if ((error = ext2_balloc(oip, lbn, offset + 1, cred, &bp, aflags)) != 0) return (error); oip->i_size = length; if (aflags & IO_SYNC) bwrite(bp); else bawrite(bp); oip->i_flag |= IN_CHANGE | IN_UPDATE; return (ext2_update(ovp, 1)); } /* * Shorten the size of the file. If the file is not being * truncated to a block boundry, the contents of the * partial block following the end of the file must be * zero'ed in case it ever become accessible again because * of subsequent file growth. */ /* I don't understand the comment above */ offset = blkoff(fs, length); if (offset == 0) { oip->i_size = length; } else { lbn = lblkno(fs, length); aflags = B_CLRBUF; if (flags & IO_SYNC) aflags |= B_SYNC; if ((error = ext2_balloc(oip, lbn, offset, cred, &bp, aflags)) != 0) return (error); oip->i_size = length; size = blksize(fs, oip, lbn); bzero((char *)bp->b_data + offset, (u_int)(size - offset)); allocbuf(bp, size); if (aflags & IO_SYNC) bwrite(bp); else bawrite(bp); } /* * Calculate index into inode's block list of * last direct and indirect blocks (if any) * which we want to keep. Lastblock is -1 when * the file is truncated to 0. */ lastblock = lblkno(fs, length + fs->s_blocksize - 1) - 1; lastiblock[SINGLE] = lastblock - NDADDR; lastiblock[DOUBLE] = lastiblock[SINGLE] - NINDIR(fs); lastiblock[TRIPLE] = lastiblock[DOUBLE] - NINDIR(fs) * NINDIR(fs); nblocks = btodb(fs->s_blocksize); /* * Update file and block pointers on disk before we start freeing * blocks. If we crash before free'ing blocks below, the blocks * will be returned to the free list. lastiblock values are also * normalized to -1 for calls to ext2_indirtrunc below. */ bcopy((caddr_t)&oip->i_db[0], (caddr_t)oldblks, sizeof oldblks); for (level = TRIPLE; level >= SINGLE; level--) if (lastiblock[level] < 0) { oip->i_ib[level] = 0; lastiblock[level] = -1; } for (i = NDADDR - 1; i > lastblock; i--) oip->i_db[i] = 0; oip->i_flag |= IN_CHANGE | IN_UPDATE; allerror = ext2_update(ovp, 1); /* * Having written the new inode to disk, save its new configuration * and put back the old block pointers long enough to process them. * Note that we save the new block configuration so we can check it * when we are done. */ bcopy((caddr_t)&oip->i_db[0], (caddr_t)newblks, sizeof newblks); bcopy((caddr_t)oldblks, (caddr_t)&oip->i_db[0], sizeof oldblks); oip->i_size = osize; error = vtruncbuf(ovp, cred, td, length, (int)fs->s_blocksize); if (error && (allerror == 0)) allerror = error; /* * Indirect blocks first. */ indir_lbn[SINGLE] = -NDADDR; indir_lbn[DOUBLE] = indir_lbn[SINGLE] - NINDIR(fs) - 1; indir_lbn[TRIPLE] = indir_lbn[DOUBLE] - NINDIR(fs) * NINDIR(fs) - 1; for (level = TRIPLE; level >= SINGLE; level--) { bn = oip->i_ib[level]; if (bn != 0) { error = ext2_indirtrunc(oip, indir_lbn[level], fsbtodb(fs, bn), lastiblock[level], level, &count); if (error) allerror = error; blocksreleased += count; if (lastiblock[level] < 0) { oip->i_ib[level] = 0; ext2_blkfree(oip, bn, fs->s_frag_size); blocksreleased += nblocks; } } if (lastiblock[level] >= 0) goto done; } /* * All whole direct blocks or frags. */ for (i = NDADDR - 1; i > lastblock; i--) { long bsize; bn = oip->i_db[i]; if (bn == 0) continue; oip->i_db[i] = 0; bsize = blksize(fs, oip, i); ext2_blkfree(oip, bn, bsize); blocksreleased += btodb(bsize); } if (lastblock < 0) goto done; /* * Finally, look for a change in size of the * last direct block; release any frags. */ bn = oip->i_db[lastblock]; if (bn != 0) { long oldspace, newspace; /* * Calculate amount of space we're giving * back as old block size minus new block size. */ oldspace = blksize(fs, oip, lastblock); oip->i_size = length; newspace = blksize(fs, oip, lastblock); if (newspace == 0) panic("itrunc: newspace"); if (oldspace - newspace > 0) { /* * Block number of space to be free'd is * the old block # plus the number of frags * required for the storage we're keeping. */ bn += numfrags(fs, newspace); ext2_blkfree(oip, bn, oldspace - newspace); blocksreleased += btodb(oldspace - newspace); } } done: #if DIAGNOSTIC for (level = SINGLE; level <= TRIPLE; level++) if (newblks[NDADDR + level] != oip->i_ib[level]) panic("itrunc1"); for (i = 0; i < NDADDR; i++) if (newblks[i] != oip->i_db[i]) panic("itrunc2"); VI_LOCK(ovp); if (length == 0 && (ovp->v_bufobj.bo_dirty.bv_cnt != 0 || ovp->v_bufobj.bo_clean.bv_cnt != 0)) panic("itrunc3"); VI_UNLOCK(ovp); #endif /* DIAGNOSTIC */ /* * Put back the real size. */ oip->i_size = length; oip->i_blocks -= blocksreleased; if (oip->i_blocks < 0) /* sanity */ oip->i_blocks = 0; oip->i_flag |= IN_CHANGE; vnode_pager_setsize(ovp, length); return (allerror); } /* * Release blocks associated with the inode ip and stored in the indirect * block bn. Blocks are free'd in LIFO order up to (but not including) * lastbn. If level is greater than SINGLE, the block is an indirect block * and recursive calls to indirtrunc must be used to cleanse other indirect * blocks. * * NB: triple indirect blocks are untested. */ static int ext2_indirtrunc(ip, lbn, dbn, lastbn, level, countp) struct inode *ip; int32_t lbn, lastbn; int32_t dbn; int level; long *countp; { struct buf *bp; struct ext2_sb_info *fs = ip->i_e2fs; struct vnode *vp; int32_t *bap, *copy, nb, nlbn, last; long blkcount, factor; int i, nblocks, blocksreleased = 0; int error = 0, allerror = 0; /* * Calculate index in current block of last * block to be kept. -1 indicates the entire * block so we need not calculate the index. */ factor = 1; for (i = SINGLE; i < level; i++) factor *= NINDIR(fs); last = lastbn; if (lastbn > 0) last /= factor; nblocks = btodb(fs->s_blocksize); /* * Get buffer of block pointers, zero those entries corresponding * to blocks to be free'd, and update on disk copy first. Since * double(triple) indirect before single(double) indirect, calls * to bmap on these blocks will fail. However, we already have * the on disk address, so we have to set the b_blkno field * explicitly instead of letting bread do everything for us. */ vp = ITOV(ip); bp = getblk(vp, lbn, (int)fs->s_blocksize, 0, 0, 0); if (bp->b_flags & (B_DONE | B_DELWRI)) { } else { bp->b_iocmd = BIO_READ; if (bp->b_bcount > bp->b_bufsize) panic("ext2_indirtrunc: bad buffer size"); bp->b_blkno = dbn; vfs_busy_pages(bp, 0); bp->b_iooffset = dbtob(bp->b_blkno); bstrategy(bp); error = bufwait(bp); } if (error) { brelse(bp); *countp = 0; return (error); } bap = (int32_t *)bp->b_data; MALLOC(copy, int32_t *, fs->s_blocksize, M_TEMP, M_WAITOK); bcopy((caddr_t)bap, (caddr_t)copy, (u_int)fs->s_blocksize); bzero((caddr_t)&bap[last + 1], (u_int)(NINDIR(fs) - (last + 1)) * sizeof (int32_t)); if (last == -1) bp->b_flags |= B_INVAL; error = bwrite(bp); if (error) allerror = error; bap = copy; /* * Recursively free totally unused blocks. */ for (i = NINDIR(fs) - 1, nlbn = lbn + 1 - i * factor; i > last; i--, nlbn += factor) { nb = bap[i]; if (nb == 0) continue; if (level > SINGLE) { if ((error = ext2_indirtrunc(ip, nlbn, fsbtodb(fs, nb), (int32_t)-1, level - 1, &blkcount)) != 0) allerror = error; blocksreleased += blkcount; } ext2_blkfree(ip, nb, fs->s_blocksize); blocksreleased += nblocks; } /* * Recursively free last partial block. */ if (level > SINGLE && lastbn >= 0) { last = lastbn % factor; nb = bap[i]; if (nb != 0) { if ((error = ext2_indirtrunc(ip, nlbn, fsbtodb(fs, nb), last, level - 1, &blkcount)) != 0) allerror = error; blocksreleased += blkcount; } } FREE(copy, M_TEMP); *countp = blocksreleased; return (allerror); } /* * discard preallocated blocks */ int ext2_inactive(ap) struct vop_inactive_args /* { struct vnode *a_vp; struct thread *a_td; } */ *ap; { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct thread *td = ap->a_td; int mode, error = 0; ext2_discard_prealloc(ip); if (prtactive && vrefcnt(vp) != 0) vprint("ext2_inactive: pushing active", vp); /* * Ignore inodes related to stale file handles. */ if (ip->i_mode == 0) goto out; if (ip->i_nlink <= 0) { (void) vn_write_suspend_wait(vp, NULL, V_WAIT); error = ext2_truncate(vp, (off_t)0, 0, NOCRED, td); ip->i_rdev = 0; mode = ip->i_mode; ip->i_mode = 0; ip->i_flag |= IN_CHANGE | IN_UPDATE; ext2_vfree(vp, ip->i_number, mode); } if (ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) { if ((ip->i_flag & (IN_CHANGE | IN_UPDATE | IN_MODIFIED)) == 0 && vn_write_suspend_wait(vp, NULL, V_NOWAIT)) { ip->i_flag &= ~IN_ACCESS; } else { (void) vn_write_suspend_wait(vp, NULL, V_WAIT); ext2_update(vp, 0); } } out: /* * If we are done with the inode, reclaim it * so that it can be reused immediately. */ if (ip->i_mode == 0) vrecycle(vp, td); return (error); } /* * Reclaim an inode so that it can be used for other purposes. */ int ext2_reclaim(ap) struct vop_reclaim_args /* { struct vnode *a_vp; struct thread *a_td; } */ *ap; { struct inode *ip; struct vnode *vp = ap->a_vp; if (prtactive && vrefcnt(vp) != 0) vprint("ufs_reclaim: pushing active", vp); ip = VTOI(vp); if (ip->i_flag & IN_LAZYMOD) { ip->i_flag |= IN_MODIFIED; ext2_update(vp, 0); } vfs_hash_remove(vp); FREE(vp->v_data, M_EXT2NODE); vp->v_data = 0; vnode_destroy_vobject(vp); return (0); } diff --git a/sys/gnu/fs/ext2fs/ext2_inode_cnv.c b/sys/gnu/fs/ext2fs/ext2_inode_cnv.c index 31deb77741a8..de30739fc51f 100644 --- a/sys/gnu/fs/ext2fs/ext2_inode_cnv.c +++ b/sys/gnu/fs/ext2fs/ext2_inode_cnv.c @@ -1,135 +1,135 @@ /*- * Copyright (c) 1995 The University of Utah and * the Computer Systems Laboratory at the University of Utah (CSL). * All rights reserved. * * Permission to use, copy, modify and distribute this software is hereby * granted provided that (1) source code retains these copyright, permission, * and disclaimer notices, and (2) redistributions including binaries * reproduce the notices in supporting documentation, and (3) all advertising * materials mentioning features or use of this software display the following * acknowledgement: ``This product includes software developed by the * Computer Systems Laboratory at the University of Utah.'' * * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * CSL requests users of this software to return to csl-dist@cs.utah.edu any * improvements that they make and grant CSL redistribution rights. * * Utah $Hdr$ * $FreeBSD$ */ /* * routines to convert on disk ext2 inodes into inodes and back */ #include #include #include #include #include -#include -#include -#include +#include +#include +#include void ext2_print_inode( in ) struct inode *in; { int i; printf( "Inode: %5d", in->i_number); printf( /* "Inode: %5d" */ " Type: %10s Mode: 0x%o Flags: 0x%x Version: %d\n", "n/a", in->i_mode, in->i_flags, in->i_gen); printf( "User: %5lu Group: %5lu Size: %lu\n", (unsigned long)in->i_uid, (unsigned long)in->i_gid, (unsigned long)in->i_size); printf( "Links: %3d Blockcount: %d\n", in->i_nlink, in->i_blocks); printf( "ctime: 0x%x", in->i_ctime); printf( "atime: 0x%x", in->i_atime); printf( "mtime: 0x%x", in->i_mtime); printf( "BLOCKS: "); for(i=0; i < (in->i_blocks <= 24 ? ((in->i_blocks+1)/2): 12); i++) printf("%d ", in->i_db[i]); printf("\n"); } /* * raw ext2 inode to inode */ void ext2_ei2i(ei, ip) struct ext2_inode *ei; struct inode *ip; { int i; ip->i_nlink = ei->i_links_count; /* Godmar thinks - if the link count is zero, then the inode is unused - according to ext2 standards. Ufs marks this fact by setting i_mode to zero - why ? I can see that this might lead to problems in an undelete. */ ip->i_mode = ei->i_links_count ? ei->i_mode : 0; ip->i_size = ei->i_size; if (S_ISREG(ip->i_mode)) ip->i_size |= ((u_int64_t)ei->i_size_high) << 32; ip->i_atime = ei->i_atime; ip->i_mtime = ei->i_mtime; ip->i_ctime = ei->i_ctime; ip->i_flags = 0; ip->i_flags |= (ei->i_flags & EXT2_APPEND_FL) ? APPEND : 0; ip->i_flags |= (ei->i_flags & EXT2_IMMUTABLE_FL) ? IMMUTABLE : 0; ip->i_blocks = ei->i_blocks; ip->i_gen = ei->i_generation; ip->i_uid = ei->i_uid; ip->i_gid = ei->i_gid; /* XXX use memcpy */ for(i = 0; i < NDADDR; i++) ip->i_db[i] = ei->i_block[i]; for(i = 0; i < NIADDR; i++) ip->i_ib[i] = ei->i_block[EXT2_NDIR_BLOCKS + i]; } /* * inode to raw ext2 inode */ void ext2_i2ei(ip, ei) struct inode *ip; struct ext2_inode *ei; { int i; ei->i_mode = ip->i_mode; ei->i_links_count = ip->i_nlink; /* Godmar thinks: if dtime is nonzero, ext2 says this inode has been deleted, this would correspond to a zero link count */ ei->i_dtime = ei->i_links_count ? 0 : ip->i_mtime; ei->i_size = ip->i_size; if (S_ISREG(ip->i_mode)) ei->i_size_high = ip->i_size >> 32; ei->i_atime = ip->i_atime; ei->i_mtime = ip->i_mtime; ei->i_ctime = ip->i_ctime; ei->i_flags = ip->i_flags; ei->i_flags = 0; ei->i_flags |= (ip->i_flags & APPEND) ? EXT2_APPEND_FL: 0; ei->i_flags |= (ip->i_flags & IMMUTABLE) ? EXT2_IMMUTABLE_FL: 0; ei->i_blocks = ip->i_blocks; ei->i_generation = ip->i_gen; ei->i_uid = ip->i_uid; ei->i_gid = ip->i_gid; /* XXX use memcpy */ for(i = 0; i < NDADDR; i++) ei->i_block[i] = ip->i_db[i]; for(i = 0; i < NIADDR; i++) ei->i_block[EXT2_NDIR_BLOCKS + i] = ip->i_ib[i]; } diff --git a/sys/gnu/fs/ext2fs/ext2_linux_balloc.c b/sys/gnu/fs/ext2fs/ext2_linux_balloc.c index 23524cac808e..86bc8c3ca2af 100644 --- a/sys/gnu/fs/ext2fs/ext2_linux_balloc.c +++ b/sys/gnu/fs/ext2fs/ext2_linux_balloc.c @@ -1,610 +1,610 @@ /*- * modified for Lites 1.1 * * Aug 1995, Godmar Back (gback@cs.utah.edu) * University of Utah, Department of Computer Science * * $FreeBSD$ */ /*- * linux/fs/ext2/balloc.c * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) * Laboratoire MASI - Institut Blaise Pascal * Universite Pierre et Marie Curie (Paris VI) * * Enhanced block allocation by Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 */ /* * The free blocks are managed by bitmaps. A file system contains several * blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap * block for inodes, N blocks for the inode table and data blocks. * * The file system contains group descriptors which are located after the * super block. Each descriptor contains the number of the bitmap block and * the free blocks count in the block. The descriptors are loaded in memory * when a file system is mounted (see ext2_read_super). */ #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #ifdef __i386__ -#include +#include #else -#include +#include #endif #define in_range(b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) /* got rid of get_group_desc since it can already be found in * ext2_linux_ialloc.c */ static void read_block_bitmap (struct mount * mp, unsigned int block_group, unsigned long bitmap_nr) { struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; struct ext2_group_desc * gdp; struct buffer_head * bh; int error; gdp = get_group_desc (mp, block_group, NULL); if ((error = bread (VFSTOEXT2(mp)->um_devvp, fsbtodb(sb, gdp->bg_block_bitmap),sb->s_blocksize, NOCRED, &bh)) != 0) panic ( "read_block_bitmap: " "Cannot read block bitmap - " "block_group = %d, block_bitmap = %lu", block_group, (unsigned long) gdp->bg_block_bitmap); sb->s_block_bitmap_number[bitmap_nr] = block_group; sb->s_block_bitmap[bitmap_nr] = bh; LCK_BUF(bh) } /* * load_block_bitmap loads the block bitmap for a blocks group * * It maintains a cache for the last bitmaps loaded. This cache is managed * with a LRU algorithm. * * Notes: * 1/ There is one cache per mounted file system. * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups, * this function reads the bitmap without maintaining a LRU cache. */ static int load__block_bitmap (struct mount * mp, unsigned int block_group) { int i, j; struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; unsigned long block_bitmap_number; struct buffer_head * block_bitmap; if (block_group >= sb->s_groups_count) panic ( "load_block_bitmap: " "block_group >= groups_count - " "block_group = %d, groups_count = %lu", block_group, sb->s_groups_count); if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED) { if (sb->s_block_bitmap[block_group]) { if (sb->s_block_bitmap_number[block_group] != block_group) panic ( "load_block_bitmap: " "block_group != block_bitmap_number"); else return block_group; } else { read_block_bitmap (mp, block_group, block_group); return block_group; } } for (i = 0; i < sb->s_loaded_block_bitmaps && sb->s_block_bitmap_number[i] != block_group; i++) ; if (i < sb->s_loaded_block_bitmaps && sb->s_block_bitmap_number[i] == block_group) { block_bitmap_number = sb->s_block_bitmap_number[i]; block_bitmap = sb->s_block_bitmap[i]; for (j = i; j > 0; j--) { sb->s_block_bitmap_number[j] = sb->s_block_bitmap_number[j - 1]; sb->s_block_bitmap[j] = sb->s_block_bitmap[j - 1]; } sb->s_block_bitmap_number[0] = block_bitmap_number; sb->s_block_bitmap[0] = block_bitmap; } else { if (sb->s_loaded_block_bitmaps < EXT2_MAX_GROUP_LOADED) sb->s_loaded_block_bitmaps++; else ULCK_BUF(sb->s_block_bitmap[EXT2_MAX_GROUP_LOADED - 1]) for (j = sb->s_loaded_block_bitmaps - 1; j > 0; j--) { sb->s_block_bitmap_number[j] = sb->s_block_bitmap_number[j - 1]; sb->s_block_bitmap[j] = sb->s_block_bitmap[j - 1]; } read_block_bitmap (mp, block_group, 0); } return 0; } static __inline int load_block_bitmap (struct mount * mp, unsigned int block_group) { struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; if (sb->s_loaded_block_bitmaps > 0 && sb->s_block_bitmap_number[0] == block_group) return 0; if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED && sb->s_block_bitmap_number[block_group] == block_group && sb->s_block_bitmap[block_group]) return block_group; return load__block_bitmap (mp, block_group); } void ext2_free_blocks (struct mount * mp, unsigned long block, unsigned long count) { struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; struct buffer_head * bh; struct buffer_head * bh2; unsigned long block_group; unsigned long bit; unsigned long i; int bitmap_nr; struct ext2_group_desc * gdp; struct ext2_super_block * es; if (!sb) { printf ("ext2_free_blocks: nonexistent device"); return; } es = sb->s_es; lock_super (VFSTOEXT2(mp)->um_devvp); if (block < es->s_first_data_block || (block + count) > es->s_blocks_count) { printf ( "ext2_free_blocks: " "Freeing blocks not in datazone - " "block = %lu, count = %lu", block, count); unlock_super (VFSTOEXT2(mp)->um_devvp); return; } ext2_debug ("freeing blocks %lu to %lu\n", block, block+count-1); block_group = (block - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb); bit = (block - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb); if (bit + count > EXT2_BLOCKS_PER_GROUP(sb)) panic ( "ext2_free_blocks: " "Freeing blocks across group boundary - " "Block = %lu, count = %lu", block, count); bitmap_nr = load_block_bitmap (mp, block_group); bh = sb->s_block_bitmap[bitmap_nr]; gdp = get_group_desc (mp, block_group, &bh2); if (/* test_opt (sb, CHECK_STRICT) && assume always strict ! */ (in_range (gdp->bg_block_bitmap, block, count) || in_range (gdp->bg_inode_bitmap, block, count) || in_range (block, gdp->bg_inode_table, sb->s_itb_per_group) || in_range (block + count - 1, gdp->bg_inode_table, sb->s_itb_per_group))) panic ( "ext2_free_blocks: " "Freeing blocks in system zones - " "Block = %lu, count = %lu", block, count); for (i = 0; i < count; i++) { if (!clear_bit (bit + i, bh->b_data)) printf ("ext2_free_blocks: " "bit already cleared for block %lu", block); else { gdp->bg_free_blocks_count++; es->s_free_blocks_count++; } } mark_buffer_dirty(bh2); mark_buffer_dirty(bh); /**** if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } ****/ sb->s_dirt = 1; unlock_super (VFSTOEXT2(mp)->um_devvp); return; } /* * ext2_new_block uses a goal block to assist allocation. If the goal is * free, or there is a free block within 32 blocks of the goal, that block * is allocated. Otherwise a forward search is made for a free block; within * each block group the search first looks for an entire free byte in the block * bitmap, and then for any free bit if that fails. */ int ext2_new_block (struct mount * mp, unsigned long goal, u_int32_t * prealloc_count, u_int32_t * prealloc_block) { struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; struct buffer_head * bh; struct buffer_head * bh2; char * p, * r; int i, j, k, tmp; int bitmap_nr; struct ext2_group_desc * gdp; struct ext2_super_block * es; #ifdef EXT2FS_DEBUG static int goal_hits = 0, goal_attempts = 0; #endif if (!sb) { printf ("ext2_new_block: nonexistent device"); return 0; } es = sb->s_es; lock_super (VFSTOEXT2(mp)->um_devvp); ext2_debug ("goal=%lu.\n", goal); repeat: /* * First, test whether the goal block is free. */ if (goal < es->s_first_data_block || goal >= es->s_blocks_count) goal = es->s_first_data_block; i = (goal - es->s_first_data_block) / EXT2_BLOCKS_PER_GROUP(sb); gdp = get_group_desc (mp, i, &bh2); if (gdp->bg_free_blocks_count > 0) { j = ((goal - es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb)); #ifdef EXT2FS_DEBUG if (j) goal_attempts++; #endif bitmap_nr = load_block_bitmap (mp, i); bh = sb->s_block_bitmap[bitmap_nr]; ext2_debug ("goal is at %d:%d.\n", i, j); if (!test_bit(j, bh->b_data)) { #ifdef EXT2FS_DEBUG goal_hits++; ext2_debug ("goal bit allocated.\n"); #endif goto got_block; } if (j) { /* * The goal was occupied; search forward for a free * block within the next XX blocks. * * end_goal is more or less random, but it has to be * less than EXT2_BLOCKS_PER_GROUP. Aligning up to the * next 64-bit boundary is simple.. */ int end_goal = (j + 63) & ~63; j = find_next_zero_bit(bh->b_data, end_goal, j); if (j < end_goal) goto got_block; } ext2_debug ("Bit not found near goal\n"); /* * There has been no free block found in the near vicinity * of the goal: do a search forward through the block groups, * searching in each group first for an entire free byte in * the bitmap and then for any free bit. * * Search first in the remainder of the current group; then, * cyclicly search through the rest of the groups. */ p = ((char *) bh->b_data) + (j >> 3); r = memscan(p, 0, (EXT2_BLOCKS_PER_GROUP(sb) - j + 7) >> 3); k = (r - ((char *) bh->b_data)) << 3; if (k < EXT2_BLOCKS_PER_GROUP(sb)) { j = k; goto search_back; } k = find_next_zero_bit ((unsigned long *) bh->b_data, EXT2_BLOCKS_PER_GROUP(sb), j); if (k < EXT2_BLOCKS_PER_GROUP(sb)) { j = k; goto got_block; } } ext2_debug ("Bit not found in block group %d.\n", i); /* * Now search the rest of the groups. We assume that * i and gdp correctly point to the last group visited. */ for (k = 0; k < sb->s_groups_count; k++) { i++; if (i >= sb->s_groups_count) i = 0; gdp = get_group_desc (mp, i, &bh2); if (gdp->bg_free_blocks_count > 0) break; } if (k >= sb->s_groups_count) { unlock_super (VFSTOEXT2(mp)->um_devvp); return 0; } bitmap_nr = load_block_bitmap (mp, i); bh = sb->s_block_bitmap[bitmap_nr]; r = memscan(bh->b_data, 0, EXT2_BLOCKS_PER_GROUP(sb) >> 3); j = (r - bh->b_data) << 3; if (j < EXT2_BLOCKS_PER_GROUP(sb)) goto search_back; else j = find_first_zero_bit ((unsigned long *) bh->b_data, EXT2_BLOCKS_PER_GROUP(sb)); if (j >= EXT2_BLOCKS_PER_GROUP(sb)) { printf ( "ext2_new_block: " "Free blocks count corrupted for block group %d", i); unlock_super (VFSTOEXT2(mp)->um_devvp); return 0; } search_back: /* * We have succeeded in finding a free byte in the block * bitmap. Now search backwards up to 7 bits to find the * start of this group of free blocks. */ for (k = 0; k < 7 && j > 0 && !test_bit (j - 1, bh->b_data); k++, j--); got_block: ext2_debug ("using block group %d(%d)\n", i, gdp->bg_free_blocks_count); tmp = j + i * EXT2_BLOCKS_PER_GROUP(sb) + es->s_first_data_block; if (/* test_opt (sb, CHECK_STRICT) && we are always strict. */ (tmp == gdp->bg_block_bitmap || tmp == gdp->bg_inode_bitmap || in_range (tmp, gdp->bg_inode_table, sb->s_itb_per_group))) panic ( "ext2_new_block: " "Allocating block in system zone - " "%dth block = %u in group %u", j, tmp, i); if (set_bit (j, bh->b_data)) { printf ( "ext2_new_block: " "bit already set for block %d", j); goto repeat; } ext2_debug ("found bit %d\n", j); /* * Do block preallocation now if required. */ #ifdef EXT2_PREALLOCATE if (prealloc_block) { *prealloc_count = 0; *prealloc_block = tmp + 1; for (k = 1; k < 8 && (j + k) < EXT2_BLOCKS_PER_GROUP(sb); k++) { if (set_bit (j + k, bh->b_data)) break; (*prealloc_count)++; } gdp->bg_free_blocks_count -= *prealloc_count; es->s_free_blocks_count -= *prealloc_count; ext2_debug ("Preallocated a further %lu bits.\n", *prealloc_count); } #endif j = tmp; mark_buffer_dirty(bh); /**** if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } ****/ if (j >= es->s_blocks_count) { printf ( "ext2_new_block: " "block >= blocks count - " "block_group = %d, block=%d", i, j); unlock_super (VFSTOEXT2(mp)->um_devvp); return 0; } ext2_debug ("allocating block %d. " "Goal hits %d of %d.\n", j, goal_hits, goal_attempts); gdp->bg_free_blocks_count--; mark_buffer_dirty(bh2); es->s_free_blocks_count--; sb->s_dirt = 1; unlock_super (VFSTOEXT2(mp)->um_devvp); return j; } #ifdef unused static unsigned long ext2_count_free_blocks (struct mount * mp) { struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; #ifdef EXT2FS_DEBUG struct ext2_super_block * es; unsigned long desc_count, bitmap_count, x; int bitmap_nr; struct ext2_group_desc * gdp; int i; lock_super (VFSTOEXT2(mp)->um_devvp); es = sb->s_es; desc_count = 0; bitmap_count = 0; gdp = NULL; for (i = 0; i < sb->s_groups_count; i++) { gdp = get_group_desc (mp, i, NULL); desc_count += gdp->bg_free_blocks_count; bitmap_nr = load_block_bitmap (mp, i); x = ext2_count_free (sb->s_block_bitmap[bitmap_nr], sb->s_blocksize); ext2_debug ("group %d: stored = %d, counted = %lu\n", i, gdp->bg_free_blocks_count, x); bitmap_count += x; } ext2_debug( "stored = %lu, computed = %lu, %lu\n", es->s_free_blocks_count, desc_count, bitmap_count); unlock_super (VFSTOEXT2(mp)->um_devvp); return bitmap_count; #else return sb->s_es->s_free_blocks_count; #endif } #endif /* unused */ static __inline int block_in_use (unsigned long block, struct ext2_sb_info * sb, unsigned char * map) { return test_bit ((block - sb->s_es->s_first_data_block) % EXT2_BLOCKS_PER_GROUP(sb), map); } static int test_root(int a, int b) { if (a == 0) return 1; while (1) { if (a == 1) return 1; if (a % b) return 0; a = a / b; } } int ext2_group_sparse(int group) { return (test_root(group, 3) || test_root(group, 5) || test_root(group, 7)); } #ifdef unused static void ext2_check_blocks_bitmap (struct mount * mp) { struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; struct buffer_head * bh; struct ext2_super_block * es; unsigned long desc_count, bitmap_count, x; unsigned long desc_blocks; int bitmap_nr; struct ext2_group_desc * gdp; int i, j; lock_super (VFSTOEXT2(mp)->um_devvp); es = sb->s_es; desc_count = 0; bitmap_count = 0; gdp = NULL; desc_blocks = (sb->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) / EXT2_DESC_PER_BLOCK(sb); for (i = 0; i < sb->s_groups_count; i++) { gdp = get_group_desc (mp, i, NULL); desc_count += gdp->bg_free_blocks_count; bitmap_nr = load_block_bitmap (mp, i); bh = sb->s_block_bitmap[bitmap_nr]; if (!(es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) || ext2_group_sparse(i)) { if (!test_bit (0, bh->b_data)) printf ("ext2_check_blocks_bitmap: " "Superblock in group %d " "is marked free", i); for (j = 0; j < desc_blocks; j++) if (!test_bit (j + 1, bh->b_data)) printf ("ext2_check_blocks_bitmap: " "Descriptor block #%d in group " "%d is marked free", j, i); } if (!block_in_use (gdp->bg_block_bitmap, sb, bh->b_data)) printf ("ext2_check_blocks_bitmap: " "Block bitmap for group %d is marked free", i); if (!block_in_use (gdp->bg_inode_bitmap, sb, bh->b_data)) printf ("ext2_check_blocks_bitmap: " "Inode bitmap for group %d is marked free", i); for (j = 0; j < sb->s_itb_per_group; j++) if (!block_in_use (gdp->bg_inode_table + j, sb, bh->b_data)) printf ("ext2_check_blocks_bitmap: " "Block #%d of the inode table in " "group %d is marked free", j, i); x = ext2_count_free (bh, sb->s_blocksize); if (gdp->bg_free_blocks_count != x) printf ("ext2_check_blocks_bitmap: " "Wrong free blocks count for group %d, " "stored = %d, counted = %lu", i, gdp->bg_free_blocks_count, x); bitmap_count += x; } if (es->s_free_blocks_count != bitmap_count) printf ("ext2_check_blocks_bitmap: " "Wrong free blocks count in super block, " "stored = %lu, counted = %lu", (unsigned long) es->s_free_blocks_count, bitmap_count); unlock_super (VFSTOEXT2(mp)->um_devvp); } #endif /* unused */ /* * this function is taken from * linux/fs/ext2/bitmap.c */ static int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; unsigned long ext2_count_free (struct buffer_head * map, unsigned int numchars) { unsigned int i; unsigned long sum = 0; if (!map) return (0); for (i = 0; i < numchars; i++) sum += nibblemap[map->b_data[i] & 0xf] + nibblemap[(map->b_data[i] >> 4) & 0xf]; return (sum); } diff --git a/sys/gnu/fs/ext2fs/ext2_linux_ialloc.c b/sys/gnu/fs/ext2fs/ext2_linux_ialloc.c index 0b656e775696..b48d62534c7c 100644 --- a/sys/gnu/fs/ext2fs/ext2_linux_ialloc.c +++ b/sys/gnu/fs/ext2fs/ext2_linux_ialloc.c @@ -1,512 +1,512 @@ /*- * modified for Lites 1.1 * * Aug 1995, Godmar Back (gback@cs.utah.edu) * University of Utah, Department of Computer Science * * $FreeBSD$ */ /*- * linux/fs/ext2/ialloc.c * * Copyright (C) 1992, 1993, 1994, 1995 * Remy Card (card@masi.ibp.fr) * Laboratoire MASI - Institut Blaise Pascal * Universite Pierre et Marie Curie (Paris VI) * * BSD ufs-inspired inode and directory allocation by * Stephen Tweedie (sct@dcs.ed.ac.uk), 1993 */ /* * The free inodes are managed by bitmaps. A file system contains several * blocks groups. Each group contains 1 bitmap block for blocks, 1 bitmap * block for inodes, N blocks for the inode table and data blocks. * * The file system contains group descriptors which are located after the * super block. Each descriptor contains the number of the bitmap block and * the free blocks count in the block. The descriptors are loaded in memory * when a file system is mounted (see ext2_read_super). */ #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #ifdef __i386__ -#include +#include #else -#include +#include #endif /* this is supposed to mark a buffer dirty on ready for delayed writing */ void mark_buffer_dirty(struct buf *bh) { int s; s = splbio(); bh->b_flags |= B_DIRTY; splx(s); } struct ext2_group_desc * get_group_desc (struct mount * mp, unsigned int block_group, struct buffer_head ** bh) { struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; unsigned long group_desc; unsigned long desc; struct ext2_group_desc * gdp; if (block_group >= sb->s_groups_count) panic ("get_group_desc: " "block_group >= groups_count - " "block_group = %d, groups_count = %lu", block_group, sb->s_groups_count); group_desc = block_group / EXT2_DESC_PER_BLOCK(sb); desc = block_group % EXT2_DESC_PER_BLOCK(sb); if (!sb->s_group_desc[group_desc]) panic ( "get_group_desc:" "Group descriptor not loaded - " "block_group = %d, group_desc = %lu, desc = %lu", block_group, group_desc, desc); gdp = (struct ext2_group_desc *) sb->s_group_desc[group_desc]->b_data; if (bh) *bh = sb->s_group_desc[group_desc]; return gdp + desc; } static void read_inode_bitmap (struct mount * mp, unsigned long block_group, unsigned int bitmap_nr) { struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; struct ext2_group_desc * gdp; struct buffer_head * bh; int error; gdp = get_group_desc (mp, block_group, NULL); if ((error = bread (VFSTOEXT2(mp)->um_devvp, fsbtodb(sb, gdp->bg_inode_bitmap), sb->s_blocksize, NOCRED, &bh)) != 0) panic ( "read_inode_bitmap:" "Cannot read inode bitmap - " "block_group = %lu, inode_bitmap = %lu", block_group, (unsigned long) gdp->bg_inode_bitmap); sb->s_inode_bitmap_number[bitmap_nr] = block_group; sb->s_inode_bitmap[bitmap_nr] = bh; LCK_BUF(bh) } /* * load_inode_bitmap loads the inode bitmap for a blocks group * * It maintains a cache for the last bitmaps loaded. This cache is managed * with a LRU algorithm. * * Notes: * 1/ There is one cache per mounted file system. * 2/ If the file system contains less than EXT2_MAX_GROUP_LOADED groups, * this function reads the bitmap without maintaining a LRU cache. */ static int load_inode_bitmap (struct mount * mp, unsigned int block_group) { struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; int i, j; unsigned long inode_bitmap_number; struct buffer_head * inode_bitmap; if (block_group >= sb->s_groups_count) panic ("load_inode_bitmap:" "block_group >= groups_count - " "block_group = %d, groups_count = %lu", block_group, sb->s_groups_count); if (sb->s_loaded_inode_bitmaps > 0 && sb->s_inode_bitmap_number[0] == block_group) return 0; if (sb->s_groups_count <= EXT2_MAX_GROUP_LOADED) { if (sb->s_inode_bitmap[block_group]) { if (sb->s_inode_bitmap_number[block_group] != block_group) panic ( "load_inode_bitmap:" "block_group != inode_bitmap_number"); else return block_group; } else { read_inode_bitmap (mp, block_group, block_group); return block_group; } } for (i = 0; i < sb->s_loaded_inode_bitmaps && sb->s_inode_bitmap_number[i] != block_group; i++) ; if (i < sb->s_loaded_inode_bitmaps && sb->s_inode_bitmap_number[i] == block_group) { inode_bitmap_number = sb->s_inode_bitmap_number[i]; inode_bitmap = sb->s_inode_bitmap[i]; for (j = i; j > 0; j--) { sb->s_inode_bitmap_number[j] = sb->s_inode_bitmap_number[j - 1]; sb->s_inode_bitmap[j] = sb->s_inode_bitmap[j - 1]; } sb->s_inode_bitmap_number[0] = inode_bitmap_number; sb->s_inode_bitmap[0] = inode_bitmap; } else { if (sb->s_loaded_inode_bitmaps < EXT2_MAX_GROUP_LOADED) sb->s_loaded_inode_bitmaps++; else ULCK_BUF(sb->s_inode_bitmap[EXT2_MAX_GROUP_LOADED - 1]) for (j = sb->s_loaded_inode_bitmaps - 1; j > 0; j--) { sb->s_inode_bitmap_number[j] = sb->s_inode_bitmap_number[j - 1]; sb->s_inode_bitmap[j] = sb->s_inode_bitmap[j - 1]; } read_inode_bitmap (mp, block_group, 0); } return 0; } void ext2_free_inode (struct inode * inode) { struct ext2_sb_info * sb; struct buffer_head * bh; struct buffer_head * bh2; unsigned long block_group; unsigned long bit; int bitmap_nr; struct ext2_group_desc * gdp; struct ext2_super_block * es; if (!inode) return; if (inode->i_nlink) { printf ("ext2_free_inode: inode has nlink=%d\n", inode->i_nlink); return; } ext2_debug ("freeing inode %lu\n", inode->i_number); sb = inode->i_e2fs; lock_super (DEVVP(inode)); if (inode->i_number < EXT2_FIRST_INO || inode->i_number > sb->s_es->s_inodes_count) { printf ("free_inode reserved inode or nonexistent inode"); unlock_super (DEVVP(inode)); return; } es = sb->s_es; block_group = (inode->i_number - 1) / EXT2_INODES_PER_GROUP(sb); bit = (inode->i_number - 1) % EXT2_INODES_PER_GROUP(sb); bitmap_nr = load_inode_bitmap (ITOV(inode)->v_mount, block_group); bh = sb->s_inode_bitmap[bitmap_nr]; if (!clear_bit (bit, bh->b_data)) printf ( "ext2_free_inode:" "bit already cleared for inode %lu", (unsigned long)inode->i_number); else { gdp = get_group_desc (ITOV(inode)->v_mount, block_group, &bh2); gdp->bg_free_inodes_count++; if (S_ISDIR(inode->i_mode)) gdp->bg_used_dirs_count--; mark_buffer_dirty(bh2); es->s_free_inodes_count++; } mark_buffer_dirty(bh); /*** XXX if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } ***/ sb->s_dirt = 1; unlock_super (DEVVP(inode)); } #if linux /* * This function increments the inode version number * * This may be used one day by the NFS server */ static void inc_inode_version (struct inode * inode, struct ext2_group_desc *gdp, int mode) { unsigned long inode_block; struct buffer_head * bh; struct ext2_inode * raw_inode; inode_block = gdp->bg_inode_table + (((inode->i_number - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) / EXT2_INODES_PER_BLOCK(inode->i_sb)); bh = bread (inode->i_sb->s_dev, inode_block, inode->i_sb->s_blocksize); if (!bh) { printf ("inc_inode_version Cannot load inode table block - " "inode=%lu, inode_block=%lu\n", inode->i_number, inode_block); inode->u.ext2_i.i_version = 1; return; } raw_inode = ((struct ext2_inode *) bh->b_data) + (((inode->i_number - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) % EXT2_INODES_PER_BLOCK(inode->i_sb)); raw_inode->i_version++; inode->u.ext2_i.i_version = raw_inode->i_version; bdwrite (bh); } #endif /* linux */ /* * There are two policies for allocating an inode. If the new inode is * a directory, then a forward search is made for a block group with both * free space and a low directory-to-inode ratio; if that fails, then of * the groups with above-average free space, that group with the fewest * directories already is chosen. * * For other inodes, search forward from the parent directory\'s block * group to find a free inode. */ /* * this functino has been reduced to the actual 'find the inode number' part */ ino_t ext2_new_inode (const struct inode * dir, int mode) { struct ext2_sb_info * sb; struct buffer_head * bh; struct buffer_head * bh2; int i, j, avefreei; int bitmap_nr; struct ext2_group_desc * gdp; struct ext2_group_desc * tmp; struct ext2_super_block * es; if (!dir) return 0; sb = dir->i_e2fs; lock_super (DEVVP(dir)); es = sb->s_es; repeat: gdp = NULL; i=0; if (S_ISDIR(mode)) { avefreei = es->s_free_inodes_count / sb->s_groups_count; /* I am not yet convinced that this next bit is necessary. i = dir->u.ext2_i.i_block_group; for (j = 0; j < sb->u.ext2_sb.s_groups_count; j++) { tmp = get_group_desc (sb, i, &bh2); if ((tmp->bg_used_dirs_count << 8) < tmp->bg_free_inodes_count) { gdp = tmp; break; } else i = ++i % sb->u.ext2_sb.s_groups_count; } */ if (!gdp) { for (j = 0; j < sb->s_groups_count; j++) { tmp = get_group_desc(ITOV(dir)->v_mount,j,&bh2); if (tmp->bg_free_inodes_count && tmp->bg_free_inodes_count >= avefreei) { if (!gdp || (tmp->bg_free_blocks_count > gdp->bg_free_blocks_count)) { i = j; gdp = tmp; } } } } } else { /* * Try to place the inode in its parent directory */ i = dir->i_block_group; tmp = get_group_desc (ITOV(dir)->v_mount, i, &bh2); if (tmp->bg_free_inodes_count) gdp = tmp; else { /* * Use a quadratic hash to find a group with a * free inode */ for (j = 1; j < sb->s_groups_count; j <<= 1) { i += j; if (i >= sb->s_groups_count) i -= sb->s_groups_count; tmp = get_group_desc(ITOV(dir)->v_mount,i,&bh2); if (tmp->bg_free_inodes_count) { gdp = tmp; break; } } } if (!gdp) { /* * That failed: try linear search for a free inode */ i = dir->i_block_group + 1; for (j = 2; j < sb->s_groups_count; j++) { if (++i >= sb->s_groups_count) i = 0; tmp = get_group_desc(ITOV(dir)->v_mount,i,&bh2); if (tmp->bg_free_inodes_count) { gdp = tmp; break; } } } } if (!gdp) { unlock_super (DEVVP(dir)); return 0; } bitmap_nr = load_inode_bitmap (ITOV(dir)->v_mount, i); bh = sb->s_inode_bitmap[bitmap_nr]; if ((j = find_first_zero_bit ((unsigned long *) bh->b_data, EXT2_INODES_PER_GROUP(sb))) < EXT2_INODES_PER_GROUP(sb)) { if (set_bit (j, bh->b_data)) { printf ( "ext2_new_inode:" "bit already set for inode %d", j); goto repeat; } /* Linux now does the following: mark_buffer_dirty(bh); if (sb->s_flags & MS_SYNCHRONOUS) { ll_rw_block (WRITE, 1, &bh); wait_on_buffer (bh); } */ mark_buffer_dirty(bh); } else { if (gdp->bg_free_inodes_count != 0) { printf ( "ext2_new_inode:" "Free inodes count corrupted in group %d", i); unlock_super (DEVVP(dir)); return 0; } goto repeat; } j += i * EXT2_INODES_PER_GROUP(sb) + 1; if (j < EXT2_FIRST_INO || j > es->s_inodes_count) { printf ( "ext2_new_inode:" "reserved inode or inode > inodes count - " "block_group = %d,inode=%d", i, j); unlock_super (DEVVP(dir)); return 0; } gdp->bg_free_inodes_count--; if (S_ISDIR(mode)) gdp->bg_used_dirs_count++; mark_buffer_dirty(bh2); es->s_free_inodes_count--; /* mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1); */ sb->s_dirt = 1; unlock_super (DEVVP(dir)); return j; } #ifdef unused static unsigned long ext2_count_free_inodes (struct mount * mp) { #ifdef EXT2FS_DEBUG struct ext2_sb_info *sb = VFSTOEXT2(mp)->um_e2fs; struct ext2_super_block * es; unsigned long desc_count, bitmap_count, x; int bitmap_nr; struct ext2_group_desc * gdp; int i; lock_super (VFSTOEXT2(mp)->um_devvp); es = sb->s_es; desc_count = 0; bitmap_count = 0; gdp = NULL; for (i = 0; i < sb->s_groups_count; i++) { gdp = get_group_desc (mp, i, NULL); desc_count += gdp->bg_free_inodes_count; bitmap_nr = load_inode_bitmap (mp, i); x = ext2_count_free (sb->s_inode_bitmap[bitmap_nr], EXT2_INODES_PER_GROUP(sb) / 8); ext2_debug ("group %d: stored = %d, counted = %lu\n", i, gdp->bg_free_inodes_count, x); bitmap_count += x; } ext2_debug("stored = %lu, computed = %lu, %lu\n", es->s_free_inodes_count, desc_count, bitmap_count); unlock_super (VFSTOEXT2(mp)->um_devvp); return desc_count; #else return VFSTOEXT2(mp)->um_e2fsb->s_free_inodes_count; #endif } #endif /* unused */ #ifdef LATER void ext2_check_inodes_bitmap (struct mount * mp) { struct ext2_super_block * es; unsigned long desc_count, bitmap_count, x; int bitmap_nr; struct ext2_group_desc * gdp; int i; lock_super (sb); es = sb->u.ext2_sb.s_es; desc_count = 0; bitmap_count = 0; gdp = NULL; for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++) { gdp = get_group_desc (sb, i, NULL); desc_count += gdp->bg_free_inodes_count; bitmap_nr = load_inode_bitmap (sb, i); x = ext2_count_free (sb->u.ext2_sb.s_inode_bitmap[bitmap_nr], EXT2_INODES_PER_GROUP(sb) / 8); if (gdp->bg_free_inodes_count != x) printf ( "ext2_check_inodes_bitmap:" "Wrong free inodes count in group %d, " "stored = %d, counted = %lu", i, gdp->bg_free_inodes_count, x); bitmap_count += x; } if (es->s_free_inodes_count != bitmap_count) printf ( "ext2_check_inodes_bitmap:" "Wrong free inodes count in super block, " "stored = %lu, counted = %lu", (unsigned long) es->s_free_inodes_count, bitmap_count); unlock_super (sb); } #endif diff --git a/sys/gnu/fs/ext2fs/ext2_lookup.c b/sys/gnu/fs/ext2fs/ext2_lookup.c index 0179f9766b2f..a23887860c9a 100644 --- a/sys/gnu/fs/ext2fs/ext2_lookup.c +++ b/sys/gnu/fs/ext2fs/ext2_lookup.c @@ -1,1080 +1,1080 @@ /*- * modified for Lites 1.1 * * Aug 1995, Godmar Back (gback@cs.utah.edu) * University of Utah, Department of Computer Science */ /*- * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)ufs_lookup.c 8.6 (Berkeley) 4/1/94 * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #ifdef DIAGNOSTIC static int dirchk = 1; #else static int dirchk = 0; #endif static SYSCTL_NODE(_vfs, OID_AUTO, e2fs, CTLFLAG_RD, 0, "EXT2FS filesystem"); SYSCTL_INT(_vfs_e2fs, OID_AUTO, dircheck, CTLFLAG_RW, &dirchk, 0, ""); /* DIRBLKSIZE in ffs is DEV_BSIZE (in most cases 512) while it is the native blocksize in ext2fs - thus, a #define is no longer appropriate */ #undef DIRBLKSIZ static u_char ext2_ft_to_dt[] = { DT_UNKNOWN, /* EXT2_FT_UNKNOWN */ DT_REG, /* EXT2_FT_REG_FILE */ DT_DIR, /* EXT2_FT_DIR */ DT_CHR, /* EXT2_FT_CHRDEV */ DT_BLK, /* EXT2_FT_BLKDEV */ DT_FIFO, /* EXT2_FT_FIFO */ DT_SOCK, /* EXT2_FT_SOCK */ DT_LNK, /* EXT2_FT_SYMLINK */ }; #define FTTODT(ft) \ ((ft) > sizeof(ext2_ft_to_dt) / sizeof(ext2_ft_to_dt[0]) ? \ DT_UNKNOWN : ext2_ft_to_dt[(ft)]) static u_char dt_to_ext2_ft[] = { EXT2_FT_UNKNOWN, /* DT_UNKNOWN */ EXT2_FT_FIFO, /* DT_FIFO */ EXT2_FT_CHRDEV, /* DT_CHR */ EXT2_FT_UNKNOWN, /* unused */ EXT2_FT_DIR, /* DT_DIR */ EXT2_FT_UNKNOWN, /* unused */ EXT2_FT_BLKDEV, /* DT_BLK */ EXT2_FT_UNKNOWN, /* unused */ EXT2_FT_REG_FILE, /* DT_REG */ EXT2_FT_UNKNOWN, /* unused */ EXT2_FT_SYMLINK, /* DT_LNK */ EXT2_FT_UNKNOWN, /* unused */ EXT2_FT_SOCK, /* DT_SOCK */ EXT2_FT_UNKNOWN, /* unused */ EXT2_FT_UNKNOWN, /* DT_WHT */ }; #define DTTOFT(dt) \ ((dt) > sizeof(dt_to_ext2_ft) / sizeof(dt_to_ext2_ft[0]) ? \ EXT2_FT_UNKNOWN : dt_to_ext2_ft[(dt)]) static int ext2_dirbadentry(struct vnode *dp, struct ext2_dir_entry_2 *de, int entryoffsetinblock); /* * Vnode op for reading directories. * * The routine below assumes that the on-disk format of a directory * is the same as that defined by . If the on-disk * format changes, then it will be necessary to do a conversion * from the on-disk format that read returns to the format defined * by . */ /* * this is exactly what we do here - the problem is that the conversion * will blow up some entries by four bytes, so it can't be done in place. * This is too bad. Right now the conversion is done entry by entry, the * converted entry is sent via uiomove. * * XXX allocate a buffer, convert as many entries as possible, then send * the whole buffer to uiomove */ int ext2_readdir(ap) struct vop_readdir_args /* { struct vnode *a_vp; struct uio *a_uio; struct ucred *a_cred; } */ *ap; { struct uio *uio = ap->a_uio; int count, error; struct ext2_dir_entry_2 *edp, *dp; int ncookies; struct dirent dstdp; struct uio auio; struct iovec aiov; caddr_t dirbuf; int DIRBLKSIZ = VTOI(ap->a_vp)->i_e2fs->s_blocksize; int readcnt; off_t startoffset = uio->uio_offset; count = uio->uio_resid; /* * Avoid complications for partial directory entries by adjusting * the i/o to end at a block boundary. Don't give up (like ufs * does) if the initial adjustment gives a negative count, since * many callers don't supply a large enough buffer. The correct * size is a little larger than DIRBLKSIZ to allow for expansion * of directory entries, but some callers just use 512. */ count -= (uio->uio_offset + count) & (DIRBLKSIZ -1); if (count <= 0) count += DIRBLKSIZ; #ifdef EXT2FS_DEBUG printf("ext2_readdir: uio_offset = %lld, uio_resid = %d, count = %d\n", uio->uio_offset, uio->uio_resid, count); #endif auio = *uio; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_resid = count; auio.uio_segflg = UIO_SYSSPACE; aiov.iov_len = count; MALLOC(dirbuf, caddr_t, count, M_TEMP, M_WAITOK); aiov.iov_base = dirbuf; error = VOP_READ(ap->a_vp, &auio, 0, ap->a_cred); if (error == 0) { readcnt = count - auio.uio_resid; edp = (struct ext2_dir_entry_2 *)&dirbuf[readcnt]; ncookies = 0; bzero(&dstdp, offsetof(struct dirent, d_name)); for (dp = (struct ext2_dir_entry_2 *)dirbuf; !error && uio->uio_resid > 0 && dp < edp; ) { /*- * "New" ext2fs directory entries differ in 3 ways * from ufs on-disk ones: * - the name is not necessarily NUL-terminated. * - the file type field always exists and always * follows the name length field. * - the file type is encoded in a different way. * * "Old" ext2fs directory entries need no special * conversions, since they are binary compatible * with "new" entries having a file type of 0 (i.e., * EXT2_FT_UNKNOWN). Splitting the old name length * field didn't make a mess like it did in ufs, * because ext2fs uses a machine-independent disk * layout. */ dstdp.d_fileno = dp->inode; dstdp.d_type = FTTODT(dp->file_type); dstdp.d_namlen = dp->name_len; dstdp.d_reclen = GENERIC_DIRSIZ(&dstdp); bcopy(dp->name, dstdp.d_name, dstdp.d_namlen); bzero(dstdp.d_name + dstdp.d_namlen, dstdp.d_reclen - offsetof(struct dirent, d_name) - dstdp.d_namlen); if (dp->rec_len > 0) { if(dstdp.d_reclen <= uio->uio_resid) { /* advance dp */ dp = (struct ext2_dir_entry_2 *) ((char *)dp + dp->rec_len); error = uiomove(&dstdp, dstdp.d_reclen, uio); if (!error) ncookies++; } else break; } else { error = EIO; break; } } /* we need to correct uio_offset */ uio->uio_offset = startoffset + (caddr_t)dp - dirbuf; if (!error && ap->a_ncookies != NULL) { u_long *cookiep, *cookies, *ecookies; off_t off; if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1) panic("ext2_readdir: unexpected uio from NFS server"); MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, M_WAITOK); off = startoffset; for (dp = (struct ext2_dir_entry_2 *)dirbuf, cookiep = cookies, ecookies = cookies + ncookies; cookiep < ecookies; dp = (struct ext2_dir_entry_2 *)((caddr_t) dp + dp->rec_len)) { off += dp->rec_len; *cookiep++ = (u_long) off; } *ap->a_ncookies = ncookies; *ap->a_cookies = cookies; } } FREE(dirbuf, M_TEMP); if (ap->a_eofflag) *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; return (error); } /* * Convert a component of a pathname into a pointer to a locked inode. * This is a very central and rather complicated routine. * If the file system is not maintained in a strict tree hierarchy, * this can result in a deadlock situation (see comments in code below). * * The cnp->cn_nameiop argument is LOOKUP, CREATE, RENAME, or DELETE depending * on whether the name is to be looked up, created, renamed, or deleted. * When CREATE, RENAME, or DELETE is specified, information usable in * creating, renaming, or deleting a directory entry may be calculated. * If flag has LOCKPARENT or'ed into it and the target of the pathname * exists, lookup returns both the target and its parent directory locked. * When creating or renaming and LOCKPARENT is specified, the target may * not be ".". When deleting and LOCKPARENT is specified, the target may * be "."., but the caller must check to ensure it does an vrele and vput * instead of two vputs. * * Overall outline of ext2_lookup: * * search for name in directory, to found or notfound * notfound: * if creating, return locked directory, leaving info on available slots * else return error * found: * if at end of path and deleting, return information to allow delete * if at end of path and rewriting (RENAME and LOCKPARENT), lock target * inode and return info to allow rewrite * if not at end, add name to cache; if at end and neither creating * nor deleting, add name to cache */ int ext2_lookup(ap) struct vop_cachedlookup_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; } */ *ap; { struct vnode *vdp; /* vnode for directory being searched */ struct inode *dp; /* inode for directory being searched */ struct buf *bp; /* a buffer of directory entries */ struct ext2_dir_entry_2 *ep; /* the current directory entry */ int entryoffsetinblock; /* offset of ep in bp's buffer */ enum {NONE, COMPACT, FOUND} slotstatus; doff_t slotoffset; /* offset of area with free space */ int slotsize; /* size of area at slotoffset */ int slotfreespace; /* amount of space free in slot */ int slotneeded; /* size of the entry we're seeking */ int numdirpasses; /* strategy for directory search */ doff_t endsearch; /* offset to end directory search */ doff_t prevoff; /* prev entry dp->i_offset */ struct vnode *pdp; /* saved dp during symlink work */ struct vnode *tdp; /* returned by VFS_VGET */ doff_t enduseful; /* pointer past last used dir slot */ u_long bmask; /* block offset mask */ int namlen, error; struct vnode **vpp = ap->a_vpp; struct componentname *cnp = ap->a_cnp; struct ucred *cred = cnp->cn_cred; int flags = cnp->cn_flags; int nameiop = cnp->cn_nameiop; struct thread *td = cnp->cn_thread; int DIRBLKSIZ = VTOI(ap->a_dvp)->i_e2fs->s_blocksize; bp = NULL; slotoffset = -1; *vpp = NULL; vdp = ap->a_dvp; dp = VTOI(vdp); /* * We now have a segment name to search for, and a directory to search. */ /* * Suppress search for slots unless creating * file and at end of pathname, in which case * we watch for a place to put the new file in * case it doesn't already exist. */ slotstatus = FOUND; slotfreespace = slotsize = slotneeded = 0; if ((nameiop == CREATE || nameiop == RENAME) && (flags & ISLASTCN)) { slotstatus = NONE; slotneeded = EXT2_DIR_REC_LEN(cnp->cn_namelen); /* was slotneeded = (sizeof(struct direct) - MAXNAMLEN + cnp->cn_namelen + 3) &~ 3; */ } /* * If there is cached information on a previous search of * this directory, pick up where we last left off. * We cache only lookups as these are the most common * and have the greatest payoff. Caching CREATE has little * benefit as it usually must search the entire directory * to determine that the entry does not exist. Caching the * location of the last DELETE or RENAME has not reduced * profiling time and hence has been removed in the interest * of simplicity. */ bmask = VFSTOEXT2(vdp->v_mount)->um_mountp->mnt_stat.f_iosize - 1; if (nameiop != LOOKUP || dp->i_diroff == 0 || dp->i_diroff > dp->i_size) { entryoffsetinblock = 0; dp->i_offset = 0; numdirpasses = 1; } else { dp->i_offset = dp->i_diroff; if ((entryoffsetinblock = dp->i_offset & bmask) && (error = ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL, &bp))) return (error); numdirpasses = 2; nchstats.ncs_2passes++; } prevoff = dp->i_offset; endsearch = roundup(dp->i_size, DIRBLKSIZ); enduseful = 0; searchloop: while (dp->i_offset < endsearch) { /* * If necessary, get the next directory block. */ if ((dp->i_offset & bmask) == 0) { if (bp != NULL) brelse(bp); if ((error = ext2_blkatoff(vdp, (off_t)dp->i_offset, NULL, &bp)) != 0) return (error); entryoffsetinblock = 0; } /* * If still looking for a slot, and at a DIRBLKSIZE * boundary, have to start looking for free space again. */ if (slotstatus == NONE && (entryoffsetinblock & (DIRBLKSIZ - 1)) == 0) { slotoffset = -1; slotfreespace = 0; } /* * Get pointer to next entry. * Full validation checks are slow, so we only check * enough to insure forward progress through the * directory. Complete checks can be run by setting * "vfs.e2fs.dirchk" to be true. */ ep = (struct ext2_dir_entry_2 *) ((char *)bp->b_data + entryoffsetinblock); if (ep->rec_len == 0 || (dirchk && ext2_dirbadentry(vdp, ep, entryoffsetinblock))) { int i; ext2_dirbad(dp, dp->i_offset, "mangled entry"); i = DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)); dp->i_offset += i; entryoffsetinblock += i; continue; } /* * If an appropriate sized slot has not yet been found, * check to see if one is available. Also accumulate space * in the current block so that we can determine if * compaction is viable. */ if (slotstatus != FOUND) { int size = ep->rec_len; if (ep->inode != 0) size -= EXT2_DIR_REC_LEN(ep->name_len); if (size > 0) { if (size >= slotneeded) { slotstatus = FOUND; slotoffset = dp->i_offset; slotsize = ep->rec_len; } else if (slotstatus == NONE) { slotfreespace += size; if (slotoffset == -1) slotoffset = dp->i_offset; if (slotfreespace >= slotneeded) { slotstatus = COMPACT; slotsize = dp->i_offset + ep->rec_len - slotoffset; } } } } /* * Check for a name match. */ if (ep->inode) { namlen = ep->name_len; if (namlen == cnp->cn_namelen && !bcmp(cnp->cn_nameptr, ep->name, (unsigned)namlen)) { /* * Save directory entry's inode number and * reclen in ndp->ni_ufs area, and release * directory buffer. */ dp->i_ino = ep->inode; dp->i_reclen = ep->rec_len; goto found; } } prevoff = dp->i_offset; dp->i_offset += ep->rec_len; entryoffsetinblock += ep->rec_len; if (ep->inode) enduseful = dp->i_offset; } /* notfound: */ /* * If we started in the middle of the directory and failed * to find our target, we must check the beginning as well. */ if (numdirpasses == 2) { numdirpasses--; dp->i_offset = 0; endsearch = dp->i_diroff; goto searchloop; } if (bp != NULL) brelse(bp); /* * If creating, and at end of pathname and current * directory has not been removed, then can consider * allowing file to be created. */ if ((nameiop == CREATE || nameiop == RENAME) && (flags & ISLASTCN) && dp->i_nlink != 0) { /* * Access for write is interpreted as allowing * creation of files in the directory. */ if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)) != 0) return (error); /* * Return an indication of where the new directory * entry should be put. If we didn't find a slot, * then set dp->i_count to 0 indicating * that the new slot belongs at the end of the * directory. If we found a slot, then the new entry * can be put in the range from dp->i_offset to * dp->i_offset + dp->i_count. */ if (slotstatus == NONE) { dp->i_offset = roundup(dp->i_size, DIRBLKSIZ); dp->i_count = 0; enduseful = dp->i_offset; } else { dp->i_offset = slotoffset; dp->i_count = slotsize; if (enduseful < slotoffset + slotsize) enduseful = slotoffset + slotsize; } dp->i_endoff = roundup(enduseful, DIRBLKSIZ); dp->i_flag |= IN_CHANGE | IN_UPDATE; /* * We return with the directory locked, so that * the parameters we set up above will still be * valid if we actually decide to do a direnter(). * We return ni_vp == NULL to indicate that the entry * does not currently exist; we leave a pointer to * the (locked) directory inode in ndp->ni_dvp. * The pathname buffer is saved so that the name * can be obtained later. * * NB - if the directory is unlocked, then this * information cannot be used. */ cnp->cn_flags |= SAVENAME; return (EJUSTRETURN); } /* * Insert name into cache (as non-existent) if appropriate. */ if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE) cache_enter(vdp, *vpp, cnp); return (ENOENT); found: if (numdirpasses == 2) nchstats.ncs_pass2++; /* * Check that directory length properly reflects presence * of this entry. */ if (entryoffsetinblock + EXT2_DIR_REC_LEN(ep->name_len) > dp->i_size) { ext2_dirbad(dp, dp->i_offset, "i_size too small"); dp->i_size = entryoffsetinblock+EXT2_DIR_REC_LEN(ep->name_len); dp->i_flag |= IN_CHANGE | IN_UPDATE; } brelse(bp); /* * Found component in pathname. * If the final component of path name, save information * in the cache as to where the entry was found. */ if ((flags & ISLASTCN) && nameiop == LOOKUP) dp->i_diroff = dp->i_offset &~ (DIRBLKSIZ - 1); /* * If deleting, and at end of pathname, return * parameters which can be used to remove file. */ if (nameiop == DELETE && (flags & ISLASTCN)) { /* * Write access to directory required to delete files. */ if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)) != 0) return (error); /* * Return pointer to current entry in dp->i_offset, * and distance past previous entry (if there * is a previous entry in this block) in dp->i_count. * Save directory inode pointer in ndp->ni_dvp for dirremove(). */ if ((dp->i_offset & (DIRBLKSIZ - 1)) == 0) dp->i_count = 0; else dp->i_count = dp->i_offset - prevoff; if (dp->i_number == dp->i_ino) { VREF(vdp); *vpp = vdp; return (0); } if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, &tdp)) != 0) return (error); /* * If directory is "sticky", then user must own * the directory, or the file in it, else she * may not delete it (unless she's root). This * implements append-only directories. */ if ((dp->i_mode & ISVTX) && cred->cr_uid != 0 && cred->cr_uid != dp->i_uid && VTOI(tdp)->i_uid != cred->cr_uid) { vput(tdp); return (EPERM); } *vpp = tdp; return (0); } /* * If rewriting (RENAME), return the inode and the * information required to rewrite the present directory * Must get inode of directory entry to verify it's a * regular file, or empty directory. */ if (nameiop == RENAME && (flags & ISLASTCN)) { if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_thread)) != 0) return (error); /* * Careful about locking second inode. * This can only occur if the target is ".". */ if (dp->i_number == dp->i_ino) return (EISDIR); if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, &tdp)) != 0) return (error); *vpp = tdp; cnp->cn_flags |= SAVENAME; return (0); } /* * Step through the translation in the name. We do not `vput' the * directory because we may need it again if a symbolic link * is relative to the current directory. Instead we save it * unlocked as "pdp". We must get the target inode before unlocking * the directory to insure that the inode will not be removed * before we get it. We prevent deadlock by always fetching * inodes from the root, moving down the directory tree. Thus * when following backward pointers ".." we must unlock the * parent directory before getting the requested directory. * There is a potential race condition here if both the current * and parent directories are removed before the VFS_VGET for the * inode associated with ".." returns. We hope that this occurs * infrequently since we cannot avoid this race condition without * implementing a sophisticated deadlock detection algorithm. * Note also that this simple deadlock detection scheme will not * work if the file system has any hard links other than ".." * that point backwards in the directory structure. */ pdp = vdp; if (flags & ISDOTDOT) { VOP_UNLOCK(pdp, 0, td); /* race to get the inode */ error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, &tdp); vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY, td); if (error != 0) return (error); *vpp = tdp; } else if (dp->i_number == dp->i_ino) { VREF(vdp); /* we want ourself, ie "." */ *vpp = vdp; } else { if ((error = VFS_VGET(vdp->v_mount, dp->i_ino, LK_EXCLUSIVE, &tdp)) != 0) return (error); *vpp = tdp; } /* * Insert name into cache if appropriate. */ if (cnp->cn_flags & MAKEENTRY) cache_enter(vdp, *vpp, cnp); return (0); } void ext2_dirbad(ip, offset, how) struct inode *ip; doff_t offset; char *how; { struct mount *mp; mp = ITOV(ip)->v_mount; (void)printf("%s: bad dir ino %lu at offset %ld: %s\n", mp->mnt_stat.f_mntonname, (u_long)ip->i_number, (long)offset, how); if ((mp->mnt_flag & MNT_RDONLY) == 0) panic("ext2_dirbad: bad dir"); } /* * Do consistency checking on a directory entry: * record length must be multiple of 4 * entry must fit in rest of its DIRBLKSIZ block * record must be large enough to contain entry * name is not longer than MAXNAMLEN * name must be as long as advertised, and null terminated */ /* * changed so that it confirms to ext2_check_dir_entry */ static int ext2_dirbadentry(dp, de, entryoffsetinblock) struct vnode *dp; struct ext2_dir_entry_2 *de; int entryoffsetinblock; { int DIRBLKSIZ = VTOI(dp)->i_e2fs->s_blocksize; char * error_msg = NULL; if (de->rec_len < EXT2_DIR_REC_LEN(1)) error_msg = "rec_len is smaller than minimal"; else if (de->rec_len % 4 != 0) error_msg = "rec_len % 4 != 0"; else if (de->rec_len < EXT2_DIR_REC_LEN(de->name_len)) error_msg = "reclen is too small for name_len"; else if (entryoffsetinblock + de->rec_len > DIRBLKSIZ) error_msg = "directory entry across blocks"; /* else LATER if (de->inode > dir->i_sb->u.ext2_sb.s_es->s_inodes_count) error_msg = "inode out of bounds"; */ if (error_msg != NULL) { printf("bad directory entry: %s\n", error_msg); printf("offset=%d, inode=%lu, rec_len=%u, name_len=%u\n", entryoffsetinblock, (unsigned long)de->inode, de->rec_len, de->name_len); } return error_msg == NULL ? 0 : 1; } /* * Write a directory entry after a call to namei, using the parameters * that it left in nameidata. The argument ip is the inode which the new * directory entry will refer to. Dvp is a pointer to the directory to * be written, which was left locked by namei. Remaining parameters * (dp->i_offset, dp->i_count) indicate how the space for the new * entry is to be obtained. */ int ext2_direnter(ip, dvp, cnp) struct inode *ip; struct vnode *dvp; struct componentname *cnp; { struct ext2_dir_entry_2 *ep, *nep; struct inode *dp; struct buf *bp; struct ext2_dir_entry_2 newdir; struct iovec aiov; struct uio auio; u_int dsize; int error, loc, newentrysize, spacefree; char *dirbuf; int DIRBLKSIZ = ip->i_e2fs->s_blocksize; #if DIAGNOSTIC if ((cnp->cn_flags & SAVENAME) == 0) panic("direnter: missing name"); #endif dp = VTOI(dvp); newdir.inode = ip->i_number; newdir.name_len = cnp->cn_namelen; if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, EXT2_FEATURE_INCOMPAT_FILETYPE)) newdir.file_type = DTTOFT(IFTODT(ip->i_mode)); else newdir.file_type = EXT2_FT_UNKNOWN; bcopy(cnp->cn_nameptr, newdir.name, (unsigned)cnp->cn_namelen + 1); newentrysize = EXT2_DIR_REC_LEN(newdir.name_len); if (dp->i_count == 0) { /* * If dp->i_count is 0, then namei could find no * space in the directory. Here, dp->i_offset will * be on a directory block boundary and we will write the * new entry into a fresh block. */ if (dp->i_offset & (DIRBLKSIZ - 1)) panic("ext2_direnter: newblk"); auio.uio_offset = dp->i_offset; newdir.rec_len = DIRBLKSIZ; auio.uio_resid = newentrysize; aiov.iov_len = newentrysize; aiov.iov_base = (caddr_t)&newdir; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_rw = UIO_WRITE; auio.uio_segflg = UIO_SYSSPACE; auio.uio_td = (struct thread *)0; error = VOP_WRITE(dvp, &auio, IO_SYNC, cnp->cn_cred); if (DIRBLKSIZ > VFSTOEXT2(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) /* XXX should grow with balloc() */ panic("ext2_direnter: frag size"); else if (!error) { dp->i_size = roundup(dp->i_size, DIRBLKSIZ); dp->i_flag |= IN_CHANGE; } return (error); } /* * If dp->i_count is non-zero, then namei found space * for the new entry in the range dp->i_offset to * dp->i_offset + dp->i_count in the directory. * To use this space, we may have to compact the entries located * there, by copying them together towards the beginning of the * block, leaving the free space in one usable chunk at the end. */ /* * Increase size of directory if entry eats into new space. * This should never push the size past a new multiple of * DIRBLKSIZE. * * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN. */ if (dp->i_offset + dp->i_count > dp->i_size) dp->i_size = dp->i_offset + dp->i_count; /* * Get the block containing the space for the new directory entry. */ if ((error = ext2_blkatoff(dvp, (off_t)dp->i_offset, &dirbuf, &bp)) != 0) return (error); /* * Find space for the new entry. In the simple case, the entry at * offset base will have the space. If it does not, then namei * arranged that compacting the region dp->i_offset to * dp->i_offset + dp->i_count would yield the * space. */ ep = (struct ext2_dir_entry_2 *)dirbuf; dsize = EXT2_DIR_REC_LEN(ep->name_len); spacefree = ep->rec_len - dsize; for (loc = ep->rec_len; loc < dp->i_count; ) { nep = (struct ext2_dir_entry_2 *)(dirbuf + loc); if (ep->inode) { /* trim the existing slot */ ep->rec_len = dsize; ep = (struct ext2_dir_entry_2 *)((char *)ep + dsize); } else { /* overwrite; nothing there; header is ours */ spacefree += dsize; } dsize = EXT2_DIR_REC_LEN(nep->name_len); spacefree += nep->rec_len - dsize; loc += nep->rec_len; bcopy((caddr_t)nep, (caddr_t)ep, dsize); } /* * Update the pointer fields in the previous entry (if any), * copy in the new entry, and write out the block. */ if (ep->inode == 0) { if (spacefree + dsize < newentrysize) panic("ext2_direnter: compact1"); newdir.rec_len = spacefree + dsize; } else { if (spacefree < newentrysize) panic("ext2_direnter: compact2"); newdir.rec_len = spacefree; ep->rec_len = dsize; ep = (struct ext2_dir_entry_2 *)((char *)ep + dsize); } bcopy((caddr_t)&newdir, (caddr_t)ep, (u_int)newentrysize); error = bwrite(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; if (!error && dp->i_endoff && dp->i_endoff < dp->i_size) error = ext2_truncate(dvp, (off_t)dp->i_endoff, IO_SYNC, cnp->cn_cred, cnp->cn_thread); return (error); } /* * Remove a directory entry after a call to namei, using * the parameters which it left in nameidata. The entry * dp->i_offset contains the offset into the directory of the * entry to be eliminated. The dp->i_count field contains the * size of the previous record in the directory. If this * is 0, the first entry is being deleted, so we need only * zero the inode number to mark the entry as free. If the * entry is not the first in the directory, we must reclaim * the space of the now empty record by adding the record size * to the size of the previous entry. */ int ext2_dirremove(dvp, cnp) struct vnode *dvp; struct componentname *cnp; { struct inode *dp; struct ext2_dir_entry_2 *ep; struct buf *bp; int error; dp = VTOI(dvp); if (dp->i_count == 0) { /* * First entry in block: set d_ino to zero. */ if ((error = ext2_blkatoff(dvp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0) return (error); ep->inode = 0; error = bwrite(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; return (error); } /* * Collapse new free space into previous entry. */ if ((error = ext2_blkatoff(dvp, (off_t)(dp->i_offset - dp->i_count), (char **)&ep, &bp)) != 0) return (error); ep->rec_len += dp->i_reclen; error = bwrite(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; return (error); } /* * Rewrite an existing directory entry to point at the inode * supplied. The parameters describing the directory entry are * set up by a call to namei. */ int ext2_dirrewrite(dp, ip, cnp) struct inode *dp, *ip; struct componentname *cnp; { struct buf *bp; struct ext2_dir_entry_2 *ep; struct vnode *vdp = ITOV(dp); int error; if ((error = ext2_blkatoff(vdp, (off_t)dp->i_offset, (char **)&ep, &bp)) != 0) return (error); ep->inode = ip->i_number; if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, EXT2_FEATURE_INCOMPAT_FILETYPE)) ep->file_type = DTTOFT(IFTODT(ip->i_mode)); else ep->file_type = EXT2_FT_UNKNOWN; error = bwrite(bp); dp->i_flag |= IN_CHANGE | IN_UPDATE; return (error); } /* * Check if a directory is empty or not. * Inode supplied must be locked. * * Using a struct dirtemplate here is not precisely * what we want, but better than using a struct direct. * * NB: does not handle corrupted directories. */ int ext2_dirempty(ip, parentino, cred) struct inode *ip; ino_t parentino; struct ucred *cred; { off_t off; struct dirtemplate dbuf; struct ext2_dir_entry_2 *dp = (struct ext2_dir_entry_2 *)&dbuf; int error, count, namlen; #define MINDIRSIZ (sizeof (struct dirtemplate) / 2) for (off = 0; off < ip->i_size; off += dp->rec_len) { error = vn_rdwr(UIO_READ, ITOV(ip), (caddr_t)dp, MINDIRSIZ, off, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, &count, (struct thread *)0); /* * Since we read MINDIRSIZ, residual must * be 0 unless we're at end of file. */ if (error || count != 0) return (0); /* avoid infinite loops */ if (dp->rec_len == 0) return (0); /* skip empty entries */ if (dp->inode == 0) continue; /* accept only "." and ".." */ namlen = dp->name_len; if (namlen > 2) return (0); if (dp->name[0] != '.') return (0); /* * At this point namlen must be 1 or 2. * 1 implies ".", 2 implies ".." if second * char is also "." */ if (namlen == 1) continue; if (dp->name[1] == '.' && dp->inode == parentino) continue; return (0); } return (1); } /* * Check if source directory is in the path of the target directory. * Target is supplied locked, source is unlocked. * The target is always vput before returning. */ int ext2_checkpath(source, target, cred) struct inode *source, *target; struct ucred *cred; { struct vnode *vp; int error, rootino, namlen; struct dirtemplate dirbuf; vp = ITOV(target); if (target->i_number == source->i_number) { error = EEXIST; goto out; } rootino = ROOTINO; error = 0; if (target->i_number == rootino) goto out; for (;;) { if (vp->v_type != VDIR) { error = ENOTDIR; break; } error = vn_rdwr(UIO_READ, vp, (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, cred, NOCRED, (int *)0, (struct thread *)0); if (error != 0) break; namlen = dirbuf.dotdot_type; /* like ufs little-endian */ if (namlen != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') { error = ENOTDIR; break; } if (dirbuf.dotdot_ino == source->i_number) { error = EINVAL; break; } if (dirbuf.dotdot_ino == rootino) break; vput(vp); if ((error = VFS_VGET(vp->v_mount, dirbuf.dotdot_ino, LK_EXCLUSIVE, &vp)) != 0) { vp = NULL; break; } } out: if (error == ENOTDIR) printf("checkpath: .. not a directory\n"); if (vp != NULL) vput(vp); return (error); } diff --git a/sys/gnu/fs/ext2fs/ext2_subr.c b/sys/gnu/fs/ext2fs/ext2_subr.c index 166e147ff16b..561784294b7b 100644 --- a/sys/gnu/fs/ext2fs/ext2_subr.c +++ b/sys/gnu/fs/ext2fs/ext2_subr.c @@ -1,120 +1,120 @@ /*- * modified for Lites 1.1 * * Aug 1995, Godmar Back (gback@cs.utah.edu) * University of Utah, Department of Computer Science */ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)ffs_subr.c 8.2 (Berkeley) 9/21/93 * $FreeBSD$ */ #include #include #include #include #include #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #ifdef KDB void ext2_checkoverlap(struct buf *, struct inode *); #endif /* * Return buffer with the contents of block "offset" from the beginning of * directory "ip". If "res" is non-zero, fill it in with a pointer to the * remaining space in the directory. */ int ext2_blkatoff(vp, offset, res, bpp) struct vnode *vp; off_t offset; char **res; struct buf **bpp; { struct inode *ip; struct ext2_sb_info *fs; struct buf *bp; int32_t lbn; int bsize, error; ip = VTOI(vp); fs = ip->i_e2fs; lbn = lblkno(fs, offset); bsize = blksize(fs, ip, lbn); *bpp = NULL; if ((error = bread(vp, lbn, bsize, NOCRED, &bp)) != 0) { brelse(bp); return (error); } if (res) *res = (char *)bp->b_data + blkoff(fs, offset); *bpp = bp; return (0); } #ifdef KDB void ext2_checkoverlap(bp, ip) struct buf *bp; struct inode *ip; { struct buf *ebp, *ep; int32_t start, last; struct vnode *vp; ebp = &buf[nbuf]; start = bp->b_blkno; last = start + btodb(bp->b_bcount) - 1; for (ep = buf; ep < ebp; ep++) { if (ep == bp || (ep->b_flags & B_INVAL)) continue; vp = ip->i_devvp; /* look for overlap */ if (ep->b_bcount == 0 || ep->b_blkno > last || ep->b_blkno + btodb(ep->b_bcount) <= start) continue; vprint("Disk overlap", vp); (void)printf("\tstart %d, end %d overlap start %lld, end %ld\n", start, last, (long long)ep->b_blkno, (long)(ep->b_blkno + btodb(ep->b_bcount) - 1)); panic("Disk buffer overlap"); } } #endif /* KDB */ diff --git a/sys/gnu/fs/ext2fs/ext2_vfsops.c b/sys/gnu/fs/ext2fs/ext2_vfsops.c index 1c77ef59e349..400c9afcfcbd 100644 --- a/sys/gnu/fs/ext2fs/ext2_vfsops.c +++ b/sys/gnu/fs/ext2fs/ext2_vfsops.c @@ -1,1128 +1,1128 @@ /*- * modified for EXT2FS support in Lites 1.1 * * Aug 1995, Godmar Back (gback@cs.utah.edu) * University of Utah, Department of Computer Science */ /*- * Copyright (c) 1989, 1991, 1993, 1994 * The Regents of the University of California. 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)ffs_vfsops.c 8.8 (Berkeley) 4/18/94 * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include -#include +#include +#include -#include -#include -#include -#include +#include +#include +#include +#include static int ext2_flushfiles(struct mount *mp, int flags, struct thread *td); static int ext2_mountfs(struct vnode *, struct mount *, struct thread *); static int ext2_reload(struct mount *mp, struct thread *td); static int ext2_sbupdate(struct ext2mount *, int); static vfs_unmount_t ext2_unmount; static vfs_root_t ext2_root; static vfs_statfs_t ext2_statfs; static vfs_sync_t ext2_sync; static vfs_vget_t ext2_vget; static vfs_fhtovp_t ext2_fhtovp; static vfs_vptofh_t ext2_vptofh; static vfs_mount_t ext2_mount; MALLOC_DEFINE(M_EXT2NODE, "EXT2 node", "EXT2 vnode private part"); static MALLOC_DEFINE(M_EXT2MNT, "EXT2 mount", "EXT2 mount structure"); static struct vfsops ext2fs_vfsops = { .vfs_fhtovp = ext2_fhtovp, .vfs_mount = ext2_mount, .vfs_root = ext2_root, /* root inode via vget */ .vfs_statfs = ext2_statfs, .vfs_sync = ext2_sync, .vfs_unmount = ext2_unmount, .vfs_vget = ext2_vget, .vfs_vptofh = ext2_vptofh, }; VFS_SET(ext2fs_vfsops, ext2fs, 0); #define bsd_malloc malloc #define bsd_free free static int ext2_check_sb_compat(struct ext2_super_block *es, struct cdev *dev, int ronly); static int compute_sb_data(struct vnode * devvp, struct ext2_super_block * es, struct ext2_sb_info * fs); static const char *ext2_opts[] = { "from", "export" }; /* * VFS Operations. * * mount system call */ static int ext2_mount(mp, td) struct mount *mp; struct thread *td; { struct export_args *export; struct vfsoptlist *opts; struct vnode *devvp; struct ext2mount *ump = 0; struct ext2_sb_info *fs; char *path, *fspec; int error, flags, len; mode_t accessmode; struct nameidata nd, *ndp = &nd; opts = mp->mnt_optnew; if (vfs_filteropt(opts, ext2_opts)) return (EINVAL); vfs_getopt(opts, "fspath", (void **)&path, NULL); /* Double-check the length of path.. */ if (strlen(path) >= MAXMNTLEN - 1) return (ENAMETOOLONG); fspec = NULL; error = vfs_getopt(opts, "from", (void **)&fspec, &len); if (!error && fspec[len - 1] != '\0') return (EINVAL); /* * If updating, check whether changing from read-only to * read/write; if there is no device name, that's all we do. */ if (mp->mnt_flag & MNT_UPDATE) { ump = VFSTOEXT2(mp); fs = ump->um_e2fs; error = 0; if (fs->s_rd_only == 0 && vfs_flagopt(opts, "ro", NULL, 0)) { error = VFS_SYNC(mp, MNT_WAIT, td); if (error) return (error); flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; if (vfs_busy(mp, LK_NOWAIT, 0, td)) return (EBUSY); error = ext2_flushfiles(mp, flags, td); vfs_unbusy(mp, td); if (!error && fs->s_wasvalid) { fs->s_es->s_state |= EXT2_VALID_FS; ext2_sbupdate(ump, MNT_WAIT); } fs->s_rd_only = 1; vfs_flagopt(opts, "ro", &mp->mnt_flag, MNT_RDONLY); DROP_GIANT(); g_topology_lock(); g_access(ump->um_cp, 0, -1, 0); g_topology_unlock(); PICKUP_GIANT(); } if (!error && (mp->mnt_flag & MNT_RELOAD)) error = ext2_reload(mp, td); if (error) return (error); devvp = ump->um_devvp; if (fs->s_rd_only && !vfs_flagopt(opts, "ro", NULL, 0)) { if (ext2_check_sb_compat(fs->s_es, devvp->v_rdev, 0)) return (EPERM); /* * If upgrade to read-write by non-root, then verify * that user has necessary permissions on the device. */ if (suser(td)) { vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); if ((error = VOP_ACCESS(devvp, VREAD | VWRITE, td->td_ucred, td)) != 0) { VOP_UNLOCK(devvp, 0, td); return (error); } VOP_UNLOCK(devvp, 0, td); } DROP_GIANT(); g_topology_lock(); error = g_access(ump->um_cp, 0, 1, 0); g_topology_unlock(); PICKUP_GIANT(); if (error) return (error); if ((fs->s_es->s_state & EXT2_VALID_FS) == 0 || (fs->s_es->s_state & EXT2_ERROR_FS)) { if (mp->mnt_flag & MNT_FORCE) { printf( "WARNING: %s was not properly dismounted\n", fs->fs_fsmnt); } else { printf( "WARNING: R/W mount of %s denied. Filesystem is not clean - run fsck\n", fs->fs_fsmnt); return (EPERM); } } fs->s_es->s_state &= ~EXT2_VALID_FS; ext2_sbupdate(ump, MNT_WAIT); fs->s_rd_only = 0; mp->mnt_flag &= ~MNT_RDONLY; } if (fspec == NULL) { error = vfs_getopt(opts, "export", (void **)&export, &len); if (error || len != sizeof(struct export_args)) return (EINVAL); /* Process export requests. */ return (vfs_export(mp, export)); } } /* * Not an update, or updating the name: look up the name * and verify that it refers to a sensible disk device. */ if (fspec == NULL) return (EINVAL); NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, td); if ((error = namei(ndp)) != 0) return (error); NDFREE(ndp, NDF_ONLY_PNBUF); devvp = ndp->ni_vp; if (!vn_isdisk(devvp, &error)) { vrele(devvp); return (error); } /* * If mount by non-root, then verify that user has necessary * permissions on the device. */ if (suser(td)) { accessmode = VREAD; if ((mp->mnt_flag & MNT_RDONLY) == 0) accessmode |= VWRITE; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); if ((error = VOP_ACCESS(devvp, accessmode, td->td_ucred, td)) != 0) { vput(devvp); return (error); } VOP_UNLOCK(devvp, 0, td); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { error = ext2_mountfs(devvp, mp, td); } else { if (devvp != ump->um_devvp) error = EINVAL; /* needs translation */ else vrele(devvp); } if (error) { vrele(devvp); return (error); } ump = VFSTOEXT2(mp); fs = ump->um_e2fs; /* * Note that this strncpy() is ok because of a check at the start * of ext2_mount(). */ strncpy(fs->fs_fsmnt, path, MAXMNTLEN); fs->fs_fsmnt[MAXMNTLEN - 1] = '\0'; vfs_mountedfrom(mp, fspec); return (0); } /* * checks that the data in the descriptor blocks make sense * this is taken from ext2/super.c */ static int ext2_check_descriptors (struct ext2_sb_info * sb) { int i; int desc_block = 0; unsigned long block = sb->s_es->s_first_data_block; struct ext2_group_desc * gdp = NULL; /* ext2_debug ("Checking group descriptors"); */ for (i = 0; i < sb->s_groups_count; i++) { /* examine next descriptor block */ if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0) gdp = (struct ext2_group_desc *) sb->s_group_desc[desc_block++]->b_data; if (gdp->bg_block_bitmap < block || gdp->bg_block_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) { printf ("ext2_check_descriptors: " "Block bitmap for group %d" " not in group (block %lu)!\n", i, (unsigned long) gdp->bg_block_bitmap); return 0; } if (gdp->bg_inode_bitmap < block || gdp->bg_inode_bitmap >= block + EXT2_BLOCKS_PER_GROUP(sb)) { printf ("ext2_check_descriptors: " "Inode bitmap for group %d" " not in group (block %lu)!\n", i, (unsigned long) gdp->bg_inode_bitmap); return 0; } if (gdp->bg_inode_table < block || gdp->bg_inode_table + sb->s_itb_per_group >= block + EXT2_BLOCKS_PER_GROUP(sb)) { printf ("ext2_check_descriptors: " "Inode table for group %d" " not in group (block %lu)!\n", i, (unsigned long) gdp->bg_inode_table); return 0; } block += EXT2_BLOCKS_PER_GROUP(sb); gdp++; } return 1; } static int ext2_check_sb_compat(es, dev, ronly) struct ext2_super_block *es; struct cdev *dev; int ronly; { if (es->s_magic != EXT2_SUPER_MAGIC) { printf("ext2fs: %s: wrong magic number %#x (expected %#x)\n", devtoname(dev), es->s_magic, EXT2_SUPER_MAGIC); return (1); } if (es->s_rev_level > EXT2_GOOD_OLD_REV) { if (es->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) { printf( "WARNING: mount of %s denied due to unsupported optional features\n", devtoname(dev)); return (1); } if (!ronly && (es->s_feature_ro_compat & ~EXT2_FEATURE_RO_COMPAT_SUPP)) { printf( "WARNING: R/W mount of %s denied due to unsupported optional features\n", devtoname(dev)); return (1); } } return (0); } /* * this computes the fields of the ext2_sb_info structure from the * data in the ext2_super_block structure read in */ static int compute_sb_data(devvp, es, fs) struct vnode * devvp; struct ext2_super_block * es; struct ext2_sb_info * fs; { int db_count, error; int i, j; int logic_sb_block = 1; /* XXX for now */ #if 1 #define V(v) #else #define V(v) printf(#v"= %d\n", fs->v); #endif fs->s_blocksize = EXT2_MIN_BLOCK_SIZE << es->s_log_block_size; V(s_blocksize) fs->s_bshift = EXT2_MIN_BLOCK_LOG_SIZE + es->s_log_block_size; V(s_bshift) fs->s_fsbtodb = es->s_log_block_size + 1; V(s_fsbtodb) fs->s_qbmask = fs->s_blocksize - 1; V(s_bmask) fs->s_blocksize_bits = EXT2_BLOCK_SIZE_BITS(es); V(s_blocksize_bits) fs->s_frag_size = EXT2_MIN_FRAG_SIZE << es->s_log_frag_size; V(s_frag_size) if (fs->s_frag_size) fs->s_frags_per_block = fs->s_blocksize / fs->s_frag_size; V(s_frags_per_block) fs->s_blocks_per_group = es->s_blocks_per_group; V(s_blocks_per_group) fs->s_frags_per_group = es->s_frags_per_group; V(s_frags_per_group) fs->s_inodes_per_group = es->s_inodes_per_group; V(s_inodes_per_group) fs->s_inodes_per_block = fs->s_blocksize / EXT2_INODE_SIZE; V(s_inodes_per_block) fs->s_itb_per_group = fs->s_inodes_per_group /fs->s_inodes_per_block; V(s_itb_per_group) fs->s_desc_per_block = fs->s_blocksize / sizeof (struct ext2_group_desc); V(s_desc_per_block) /* s_resuid / s_resgid ? */ fs->s_groups_count = (es->s_blocks_count - es->s_first_data_block + EXT2_BLOCKS_PER_GROUP(fs) - 1) / EXT2_BLOCKS_PER_GROUP(fs); V(s_groups_count) db_count = (fs->s_groups_count + EXT2_DESC_PER_BLOCK(fs) - 1) / EXT2_DESC_PER_BLOCK(fs); fs->s_db_per_group = db_count; V(s_db_per_group) fs->s_group_desc = bsd_malloc(db_count * sizeof (struct buf *), M_EXT2MNT, M_WAITOK); /* adjust logic_sb_block */ if(fs->s_blocksize > SBSIZE) /* Godmar thinks: if the blocksize is greater than 1024, then the superblock is logically part of block zero. */ logic_sb_block = 0; for (i = 0; i < db_count; i++) { error = bread(devvp , fsbtodb(fs, logic_sb_block + i + 1), fs->s_blocksize, NOCRED, &fs->s_group_desc[i]); if(error) { for (j = 0; j < i; j++) brelse(fs->s_group_desc[j]); bsd_free(fs->s_group_desc, M_EXT2MNT); printf("EXT2-fs: unable to read group descriptors (%d)\n", error); return EIO; } LCK_BUF(fs->s_group_desc[i]) } if(!ext2_check_descriptors(fs)) { for (j = 0; j < db_count; j++) ULCK_BUF(fs->s_group_desc[j]) bsd_free(fs->s_group_desc, M_EXT2MNT); printf("EXT2-fs: (ext2_check_descriptors failure) " "unable to read group descriptors\n"); return EIO; } for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) { fs->s_inode_bitmap_number[i] = 0; fs->s_inode_bitmap[i] = NULL; fs->s_block_bitmap_number[i] = 0; fs->s_block_bitmap[i] = NULL; } fs->s_loaded_inode_bitmaps = 0; fs->s_loaded_block_bitmaps = 0; if (es->s_rev_level == EXT2_GOOD_OLD_REV || (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_LARGE_FILE) == 0) fs->fs_maxfilesize = 0x7fffffff; else fs->fs_maxfilesize = 0x7fffffffffffffff; return 0; } /* * Reload all incore data for a filesystem (used after running fsck on * the root filesystem and finding things to fix). The filesystem must * be mounted read-only. * * Things to do to update the mount: * 1) invalidate all cached meta-data. * 2) re-read superblock from disk. * 3) re-read summary information from disk. * 4) invalidate all inactive vnodes. * 5) invalidate all cached file data. * 6) re-read inode data for all active vnodes. */ static int ext2_reload(struct mount *mp, struct thread *td) { struct vnode *vp, *nvp, *devvp; struct inode *ip; struct buf *bp; struct ext2_super_block * es; struct ext2_sb_info *fs; int error; if ((mp->mnt_flag & MNT_RDONLY) == 0) return (EINVAL); /* * Step 1: invalidate all cached meta-data. */ devvp = VFSTOEXT2(mp)->um_devvp; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, td); if (vinvalbuf(devvp, 0, td, 0, 0) != 0) panic("ext2_reload: dirty1"); VOP_UNLOCK(devvp, 0, td); /* * Step 2: re-read superblock from disk. * constants have been adjusted for ext2 */ if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0) return (error); es = (struct ext2_super_block *)bp->b_data; if (ext2_check_sb_compat(es, devvp->v_rdev, 0) != 0) { brelse(bp); return (EIO); /* XXX needs translation */ } fs = VFSTOEXT2(mp)->um_e2fs; bcopy(bp->b_data, fs->s_es, sizeof(struct ext2_super_block)); if((error = compute_sb_data(devvp, es, fs)) != 0) { brelse(bp); return error; } #ifdef UNKLAR if (fs->fs_sbsize < SBSIZE) bp->b_flags |= B_INVAL; #endif brelse(bp); loop: MNT_ILOCK(mp); MNT_VNODE_FOREACH(vp, mp, nvp) { VI_LOCK(vp); if (vp->v_iflag & VI_DOOMED) { VI_UNLOCK(vp); continue; } MNT_IUNLOCK(mp); /* * Step 4: invalidate all cached file data. */ if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK, td)) { goto loop; } if (vinvalbuf(vp, 0, td, 0, 0)) panic("ext2_reload: dirty2"); /* * Step 5: re-read inode data for all active vnodes. */ ip = VTOI(vp); error = bread(devvp, fsbtodb(fs, ino_to_fsba(fs, ip->i_number)), (int)fs->s_blocksize, NOCRED, &bp); if (error) { VOP_UNLOCK(vp, 0, td); vrele(vp); return (error); } ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE * ino_to_fsbo(fs, ip->i_number)), ip); brelse(bp); VOP_UNLOCK(vp, 0, td); vrele(vp); MNT_ILOCK(mp); } MNT_IUNLOCK(mp); return (0); } /* * Common code for mount and mountroot */ static int ext2_mountfs(devvp, mp, td) struct vnode *devvp; struct mount *mp; struct thread *td; { struct ext2mount *ump; struct buf *bp; struct ext2_sb_info *fs; struct ext2_super_block * es; struct cdev *dev = devvp->v_rdev; struct g_consumer *cp; struct bufobj *bo; int error; int ronly; ronly = vfs_flagopt(mp->mnt_optnew, "ro", NULL, 0); /* XXX: use VOP_ACESS to check FS perms */ DROP_GIANT(); g_topology_lock(); error = g_vfs_open(devvp, &cp, "ext2fs", ronly ? 0 : 1); g_topology_unlock(); PICKUP_GIANT(); VOP_UNLOCK(devvp, 0, td); if (error) return (error); bo = &devvp->v_bufobj; bo->bo_private = cp; bo->bo_ops = g_vfs_bufops; if (devvp->v_rdev->si_iosize_max != 0) mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max; if (mp->mnt_iosize_max > MAXPHYS) mp->mnt_iosize_max = MAXPHYS; bp = NULL; ump = NULL; if ((error = bread(devvp, SBLOCK, SBSIZE, NOCRED, &bp)) != 0) goto out; es = (struct ext2_super_block *)bp->b_data; if (ext2_check_sb_compat(es, dev, ronly) != 0) { error = EINVAL; /* XXX needs translation */ goto out; } if ((es->s_state & EXT2_VALID_FS) == 0 || (es->s_state & EXT2_ERROR_FS)) { if (ronly || (mp->mnt_flag & MNT_FORCE)) { printf( "WARNING: Filesystem was not properly dismounted\n"); } else { printf( "WARNING: R/W mount denied. Filesystem is not clean - run fsck\n"); error = EPERM; goto out; } } ump = bsd_malloc(sizeof *ump, M_EXT2MNT, M_WAITOK); bzero((caddr_t)ump, sizeof *ump); /* I don't know whether this is the right strategy. Note that we dynamically allocate both an ext2_sb_info and an ext2_super_block while Linux keeps the super block in a locked buffer */ ump->um_e2fs = bsd_malloc(sizeof(struct ext2_sb_info), M_EXT2MNT, M_WAITOK); ump->um_e2fs->s_es = bsd_malloc(sizeof(struct ext2_super_block), M_EXT2MNT, M_WAITOK); bcopy(es, ump->um_e2fs->s_es, (u_int)sizeof(struct ext2_super_block)); if ((error = compute_sb_data(devvp, ump->um_e2fs->s_es, ump->um_e2fs))) goto out; /* * We don't free the group descriptors allocated by compute_sb_data() * until ext2_unmount(). This is OK since the mount will succeed. */ brelse(bp); bp = NULL; fs = ump->um_e2fs; fs->s_rd_only = ronly; /* ronly is set according to mnt_flags */ /* if the fs is not mounted read-only, make sure the super block is always written back on a sync() */ fs->s_wasvalid = fs->s_es->s_state & EXT2_VALID_FS ? 1 : 0; if (ronly == 0) { fs->s_dirt = 1; /* mark it modified */ fs->s_es->s_state &= ~EXT2_VALID_FS; /* set fs invalid */ } mp->mnt_data = (qaddr_t)ump; mp->mnt_stat.f_fsid.val[0] = dev2udev(dev); mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; mp->mnt_maxsymlinklen = EXT2_MAXSYMLINKLEN; mp->mnt_flag |= MNT_LOCAL; ump->um_mountp = mp; ump->um_dev = dev; ump->um_devvp = devvp; ump->um_bo = &devvp->v_bufobj; ump->um_cp = cp; /* setting those two parameters allowed us to use ufs_bmap w/o changse ! */ ump->um_nindir = EXT2_ADDR_PER_BLOCK(fs); ump->um_bptrtodb = fs->s_es->s_log_block_size + 1; ump->um_seqinc = EXT2_FRAGS_PER_BLOCK(fs); if (ronly == 0) ext2_sbupdate(ump, MNT_WAIT); return (0); out: if (bp) brelse(bp); if (cp != NULL) { DROP_GIANT(); g_topology_lock(); g_vfs_close(cp, td); g_topology_unlock(); PICKUP_GIANT(); } if (ump) { bsd_free(ump->um_e2fs->s_es, M_EXT2MNT); bsd_free(ump->um_e2fs, M_EXT2MNT); bsd_free(ump, M_EXT2MNT); mp->mnt_data = (qaddr_t)0; } return (error); } /* * unmount system call */ static int ext2_unmount(mp, mntflags, td) struct mount *mp; int mntflags; struct thread *td; { struct ext2mount *ump; struct ext2_sb_info *fs; int error, flags, ronly, i; flags = 0; if (mntflags & MNT_FORCE) { if (mp->mnt_flag & MNT_ROOTFS) return (EINVAL); flags |= FORCECLOSE; } if ((error = ext2_flushfiles(mp, flags, td)) != 0) return (error); ump = VFSTOEXT2(mp); fs = ump->um_e2fs; ronly = fs->s_rd_only; if (ronly == 0) { if (fs->s_wasvalid) fs->s_es->s_state |= EXT2_VALID_FS; ext2_sbupdate(ump, MNT_WAIT); } /* release buffers containing group descriptors */ for(i = 0; i < fs->s_db_per_group; i++) ULCK_BUF(fs->s_group_desc[i]) bsd_free(fs->s_group_desc, M_EXT2MNT); /* release cached inode/block bitmaps */ for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) if (fs->s_inode_bitmap[i]) ULCK_BUF(fs->s_inode_bitmap[i]) for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++) if (fs->s_block_bitmap[i]) ULCK_BUF(fs->s_block_bitmap[i]) DROP_GIANT(); g_topology_lock(); g_vfs_close(ump->um_cp, td); g_topology_unlock(); PICKUP_GIANT(); vrele(ump->um_devvp); bsd_free(fs->s_es, M_EXT2MNT); bsd_free(fs, M_EXT2MNT); bsd_free(ump, M_EXT2MNT); mp->mnt_data = (qaddr_t)0; mp->mnt_flag &= ~MNT_LOCAL; return (error); } /* * Flush out all the files in a filesystem. */ static int ext2_flushfiles(mp, flags, td) struct mount *mp; int flags; struct thread *td; { int error; error = vflush(mp, 0, flags, td); return (error); } /* * Get file system statistics. * taken from ext2/super.c ext2_statfs */ static int ext2_statfs(mp, sbp, td) struct mount *mp; struct statfs *sbp; struct thread *td; { unsigned long overhead; struct ext2mount *ump; struct ext2_sb_info *fs; struct ext2_super_block *es; int i, nsb; ump = VFSTOEXT2(mp); fs = ump->um_e2fs; es = fs->s_es; if (es->s_magic != EXT2_SUPER_MAGIC) panic("ext2_statfs - magic number spoiled"); /* * Compute the overhead (FS structures) */ if (es->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) { nsb = 0; for (i = 0 ; i < fs->s_groups_count; i++) if (ext2_group_sparse(i)) nsb++; } else nsb = fs->s_groups_count; overhead = es->s_first_data_block + /* Superblocks and block group descriptors: */ nsb * (1 + fs->s_db_per_group) + /* Inode bitmap, block bitmap, and inode table: */ fs->s_groups_count * (1 + 1 + fs->s_itb_per_group); sbp->f_bsize = EXT2_FRAG_SIZE(fs); sbp->f_iosize = EXT2_BLOCK_SIZE(fs); sbp->f_blocks = es->s_blocks_count - overhead; sbp->f_bfree = es->s_free_blocks_count; sbp->f_bavail = sbp->f_bfree - es->s_r_blocks_count; sbp->f_files = es->s_inodes_count; sbp->f_ffree = es->s_free_inodes_count; return (0); } /* * Go through the disk queues to initiate sandbagged IO; * go through the inodes to write those that have been modified; * initiate the writing of the super block if it has been modified. * * Note: we are always called with the filesystem marked `MPBUSY'. */ static int ext2_sync(mp, waitfor, td) struct mount *mp; int waitfor; struct thread *td; { struct vnode *nvp, *vp; struct inode *ip; struct ext2mount *ump = VFSTOEXT2(mp); struct ext2_sb_info *fs; int error, allerror = 0; fs = ump->um_e2fs; if (fs->s_dirt != 0 && fs->s_rd_only != 0) { /* XXX */ printf("fs = %s\n", fs->fs_fsmnt); panic("ext2_sync: rofs mod"); } /* * Write back each (modified) inode. */ MNT_ILOCK(mp); loop: MNT_VNODE_FOREACH(vp, mp, nvp) { VI_LOCK(vp); if (vp->v_type == VNON || (vp->v_iflag & VI_DOOMED)) { VI_UNLOCK(vp); continue; } MNT_IUNLOCK(mp); ip = VTOI(vp); if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_MODIFIED | IN_UPDATE)) == 0 && (vp->v_bufobj.bo_dirty.bv_cnt == 0 || waitfor == MNT_LAZY)) { VI_UNLOCK(vp); MNT_ILOCK(mp); continue; } error = vget(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_INTERLOCK, td); if (error) { MNT_ILOCK(mp); if (error == ENOENT) goto loop; continue; } if ((error = VOP_FSYNC(vp, waitfor, td)) != 0) allerror = error; VOP_UNLOCK(vp, 0, td); vrele(vp); MNT_ILOCK(mp); } MNT_IUNLOCK(mp); /* * Force stale file system control information to be flushed. */ if (waitfor != MNT_LAZY) { vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY, td); if ((error = VOP_FSYNC(ump->um_devvp, waitfor, td)) != 0) allerror = error; VOP_UNLOCK(ump->um_devvp, 0, td); } /* * Write back modified superblock. */ if (fs->s_dirt != 0) { fs->s_dirt = 0; fs->s_es->s_wtime = time_second; if ((error = ext2_sbupdate(ump, waitfor)) != 0) allerror = error; } return (allerror); } /* * Look up an EXT2FS dinode number to find its incore vnode, otherwise read it * in from disk. If it is in core, wait for the lock bit to clear, then * return the inode locked. Detection and handling of mount points must be * done by the calling routine. */ static int ext2_vget(mp, ino, flags, vpp) struct mount *mp; ino_t ino; int flags; struct vnode **vpp; { struct ext2_sb_info *fs; struct inode *ip; struct ext2mount *ump; struct buf *bp; struct vnode *vp; struct cdev *dev; int i, error; int used_blocks; error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL); if (error || *vpp != NULL) return (error); ump = VFSTOEXT2(mp); dev = ump->um_dev; /* * If this MALLOC() is performed after the getnewvnode() * it might block, leaving a vnode with a NULL v_data to be * found by ext2_sync() if a sync happens to fire right then, * which will cause a panic because ext2_sync() blindly * dereferences vp->v_data (as well it should). */ ip = malloc(sizeof(struct inode), M_EXT2NODE, M_WAITOK | M_ZERO); /* Allocate a new vnode/inode. */ if ((error = getnewvnode("ext2fs", mp, &ext2_vnodeops, &vp)) != 0) { *vpp = NULL; free(ip, M_EXT2NODE); return (error); } vp->v_data = ip; ip->i_vnode = vp; ip->i_e2fs = fs = ump->um_e2fs; ip->i_number = ino; error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL); if (error || *vpp != NULL) return (error); /* Read in the disk contents for the inode, copy into the inode. */ #if 0 printf("ext2_vget(%d) dbn= %d ", ino, fsbtodb(fs, ino_to_fsba(fs, ino))); #endif if ((error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), (int)fs->s_blocksize, NOCRED, &bp)) != 0) { /* * The inode does not contain anything useful, so it would * be misleading to leave it on its hash chain. With mode * still zero, it will be unlinked and returned to the free * list by vput(). */ vput(vp); brelse(bp); *vpp = NULL; return (error); } /* convert ext2 inode to dinode */ ext2_ei2i((struct ext2_inode *) ((char *)bp->b_data + EXT2_INODE_SIZE * ino_to_fsbo(fs, ino)), ip); ip->i_block_group = ino_to_cg(fs, ino); ip->i_next_alloc_block = 0; ip->i_next_alloc_goal = 0; ip->i_prealloc_count = 0; ip->i_prealloc_block = 0; /* now we want to make sure that block pointers for unused blocks are zeroed out - ext2_balloc depends on this although for regular files and directories only */ if(S_ISDIR(ip->i_mode) || S_ISREG(ip->i_mode)) { used_blocks = (ip->i_size+fs->s_blocksize-1) / fs->s_blocksize; for(i = used_blocks; i < EXT2_NDIR_BLOCKS; i++) ip->i_db[i] = 0; } /* ext2_print_inode(ip); */ brelse(bp); /* * Initialize the vnode from the inode, check for aliases. * Note that the underlying vnode may have changed. */ if ((error = ext2_vinit(mp, &ext2_fifoops, &vp)) != 0) { vput(vp); *vpp = NULL; return (error); } /* * Finish inode initialization now that aliasing has been resolved. */ ip->i_devvp = ump->um_devvp; /* * Set up a generation number for this inode if it does not * already have one. This should only happen on old filesystems. */ if (ip->i_gen == 0) { ip->i_gen = random() / 2 + 1; if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) ip->i_flag |= IN_MODIFIED; } *vpp = vp; return (0); } /* * File handle to vnode * * Have to be really careful about stale file handles: * - check that the inode number is valid * - call ext2_vget() to get the locked inode * - check for an unallocated inode (i_mode == 0) * - check that the given client host has export rights and return * those rights via. exflagsp and credanonp */ static int ext2_fhtovp(mp, fhp, vpp) struct mount *mp; struct fid *fhp; struct vnode **vpp; { struct inode *ip; struct ufid *ufhp; struct vnode *nvp; struct ext2_sb_info *fs; int error; ufhp = (struct ufid *)fhp; fs = VFSTOEXT2(mp)->um_e2fs; if (ufhp->ufid_ino < ROOTINO || ufhp->ufid_ino > fs->s_groups_count * fs->s_es->s_inodes_per_group) return (ESTALE); error = VFS_VGET(mp, ufhp->ufid_ino, LK_EXCLUSIVE, &nvp); if (error) { *vpp = NULLVP; return (error); } ip = VTOI(nvp); if (ip->i_mode == 0 || ip->i_gen != ufhp->ufid_gen || ip->i_nlink <= 0) { vput(nvp); *vpp = NULLVP; return (ESTALE); } *vpp = nvp; vnode_create_vobject(*vpp, 0, curthread); return (0); } /* * Vnode pointer to File handle */ /* ARGSUSED */ static int ext2_vptofh(vp, fhp) struct vnode *vp; struct fid *fhp; { struct inode *ip; struct ufid *ufhp; ip = VTOI(vp); ufhp = (struct ufid *)fhp; ufhp->ufid_len = sizeof(struct ufid); ufhp->ufid_ino = ip->i_number; ufhp->ufid_gen = ip->i_gen; return (0); } /* * Write a superblock and associated information back to disk. */ static int ext2_sbupdate(mp, waitfor) struct ext2mount *mp; int waitfor; { struct ext2_sb_info *fs = mp->um_e2fs; struct ext2_super_block *es = fs->s_es; struct buf *bp; int error = 0; /* printf("\nupdating superblock, waitfor=%s\n", waitfor == MNT_WAIT ? "yes":"no"); */ bp = getblk(mp->um_devvp, SBLOCK, SBSIZE, 0, 0, 0); bcopy((caddr_t)es, bp->b_data, (u_int)sizeof(struct ext2_super_block)); if (waitfor == MNT_WAIT) error = bwrite(bp); else bawrite(bp); /* * The buffers for group descriptors, inode bitmaps and block bitmaps * are not busy at this point and are (hopefully) written by the * usual sync mechanism. No need to write them here */ return (error); } /* * Return the root of a filesystem. */ static int ext2_root(mp, flags, vpp, td) struct mount *mp; int flags; struct vnode **vpp; struct thread *td; { struct vnode *nvp; int error; error = VFS_VGET(mp, (ino_t)ROOTINO, LK_EXCLUSIVE, &nvp); if (error) return (error); *vpp = nvp; return (0); } diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c index 56ead88ad472..b97be20f6b2b 100644 --- a/sys/gnu/fs/ext2fs/ext2_vnops.c +++ b/sys/gnu/fs/ext2fs/ext2_vnops.c @@ -1,1741 +1,1741 @@ /*- * modified for EXT2FS support in Lites 1.1 * * Aug 1995, Godmar Back (gback@cs.utah.edu) * University of Utah, Department of Computer Science */ /*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * @(#)ufs_vnops.c 8.7 (Berkeley) 2/3/94 * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95 * $FreeBSD$ */ #include "opt_suiddir.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include static int ext2_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *); static vop_access_t ext2_access; static vop_advlock_t ext2_advlock; static int ext2_chmod(struct vnode *, int, struct ucred *, struct thread *); static int ext2_chown(struct vnode *, uid_t, gid_t, struct ucred *, struct thread *); static vop_close_t ext2_close; static vop_create_t ext2_create; static vop_fsync_t ext2_fsync; static vop_getattr_t ext2_getattr; static vop_kqfilter_t ext2_kqfilter; static vop_link_t ext2_link; static vop_mkdir_t ext2_mkdir; static vop_mknod_t ext2_mknod; static vop_open_t ext2_open; static vop_pathconf_t ext2_pathconf; static vop_print_t ext2_print; static vop_read_t ext2_read; static vop_readlink_t ext2_readlink; static vop_remove_t ext2_remove; static vop_rename_t ext2_rename; static vop_rmdir_t ext2_rmdir; static vop_setattr_t ext2_setattr; static vop_strategy_t ext2_strategy; static vop_symlink_t ext2_symlink; static vop_write_t ext2_write; static vop_close_t ext2fifo_close; static vop_kqfilter_t ext2fifo_kqfilter; static int filt_ext2read(struct knote *kn, long hint); static int filt_ext2write(struct knote *kn, long hint); static int filt_ext2vnode(struct knote *kn, long hint); static void filt_ext2detach(struct knote *kn); /* Global vfs data structures for ext2. */ struct vop_vector ext2_vnodeops = { .vop_default = &default_vnodeops, .vop_access = ext2_access, .vop_advlock = ext2_advlock, .vop_bmap = ext2_bmap, .vop_cachedlookup = ext2_lookup, .vop_close = ext2_close, .vop_create = ext2_create, .vop_fsync = ext2_fsync, .vop_getattr = ext2_getattr, .vop_inactive = ext2_inactive, .vop_link = ext2_link, .vop_lookup = vfs_cache_lookup, .vop_mkdir = ext2_mkdir, .vop_mknod = ext2_mknod, .vop_open = ext2_open, .vop_pathconf = ext2_pathconf, .vop_poll = vop_stdpoll, .vop_kqfilter = ext2_kqfilter, .vop_print = ext2_print, .vop_read = ext2_read, .vop_readdir = ext2_readdir, .vop_readlink = ext2_readlink, .vop_reallocblks = ext2_reallocblks, .vop_reclaim = ext2_reclaim, .vop_remove = ext2_remove, .vop_rename = ext2_rename, .vop_rmdir = ext2_rmdir, .vop_setattr = ext2_setattr, .vop_strategy = ext2_strategy, .vop_symlink = ext2_symlink, .vop_write = ext2_write, }; struct vop_vector ext2_fifoops = { .vop_default = &fifo_specops, .vop_access = ext2_access, .vop_close = ext2fifo_close, .vop_fsync = ext2_fsync, .vop_getattr = ext2_getattr, .vop_inactive = ext2_inactive, .vop_kqfilter = ext2fifo_kqfilter, .vop_print = ext2_print, .vop_read = VOP_PANIC, .vop_reclaim = ext2_reclaim, .vop_setattr = ext2_setattr, .vop_write = VOP_PANIC, }; -#include +#include /* * A virgin directory (no blushing please). * Note that the type and namlen fields are reversed relative to ext2. * Also, we don't use `struct odirtemplate', since it would just cause * endianness problems. */ static struct dirtemplate mastertemplate = { 0, 12, 1, EXT2_FT_DIR, ".", 0, DIRBLKSIZ - 12, 2, EXT2_FT_DIR, ".." }; static struct dirtemplate omastertemplate = { 0, 12, 1, EXT2_FT_UNKNOWN, ".", 0, DIRBLKSIZ - 12, 2, EXT2_FT_UNKNOWN, ".." }; void ext2_itimes(vp) struct vnode *vp; { struct inode *ip; struct timespec ts; ip = VTOI(vp); if ((ip->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE)) == 0) return; if ((vp->v_type == VBLK || vp->v_type == VCHR)) ip->i_flag |= IN_LAZYMOD; else ip->i_flag |= IN_MODIFIED; if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { vfs_timestamp(&ts); if (ip->i_flag & IN_ACCESS) { ip->i_atime = ts.tv_sec; ip->i_atimensec = ts.tv_nsec; } if (ip->i_flag & IN_UPDATE) { ip->i_mtime = ts.tv_sec; ip->i_mtimensec = ts.tv_nsec; ip->i_modrev++; } if (ip->i_flag & IN_CHANGE) { ip->i_ctime = ts.tv_sec; ip->i_ctimensec = ts.tv_nsec; } } ip->i_flag &= ~(IN_ACCESS | IN_CHANGE | IN_UPDATE); } /* * Create a regular file */ static int ext2_create(ap) struct vop_create_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; } */ *ap; { int error; error = ext2_makeinode(MAKEIMODE(ap->a_vap->va_type, ap->a_vap->va_mode), ap->a_dvp, ap->a_vpp, ap->a_cnp); if (error) return (error); return (0); } /* * Open called. * * Nothing to do. */ static int ext2_open(ap) struct vop_open_args /* { struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct thread *a_td; } */ *ap; { if (ap->a_vp->v_type == VBLK || ap->a_vp->v_type == VCHR) return (EOPNOTSUPP); /* * Files marked append-only must be opened for appending. */ if ((VTOI(ap->a_vp)->i_flags & APPEND) && (ap->a_mode & (FWRITE | O_APPEND)) == FWRITE) return (EPERM); return (0); } /* * Close called. * * Update the times on the inode. */ static int ext2_close(ap) struct vop_close_args /* { struct vnode *a_vp; int a_fflag; struct ucred *a_cred; struct thread *a_td; } */ *ap; { struct vnode *vp = ap->a_vp; VI_LOCK(vp); if (vp->v_usecount > 1) ext2_itimes(vp); VI_UNLOCK(vp); return (0); } static int ext2_access(ap) struct vop_access_args /* { struct vnode *a_vp; int a_mode; struct ucred *a_cred; struct thread *a_td; } */ *ap; { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); mode_t mode = ap->a_mode; int error; if (vp->v_type == VBLK || vp->v_type == VCHR) return (EOPNOTSUPP); /* * Disallow write attempts on read-only file systems; * unless the file is a socket, fifo, or a block or * character device resident on the file system. */ if (mode & VWRITE) { switch (vp->v_type) { case VDIR: case VLNK: case VREG: if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); break; default: break; } } /* If immutable bit set, nobody gets to write it. */ if ((mode & VWRITE) && (ip->i_flags & (IMMUTABLE | SF_SNAPSHOT))) return (EPERM); error = vaccess(vp->v_type, ip->i_mode, ip->i_uid, ip->i_gid, ap->a_mode, ap->a_cred, NULL); return (error); } static int ext2_getattr(ap) struct vop_getattr_args /* { struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct thread *a_td; } */ *ap; { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct vattr *vap = ap->a_vap; ext2_itimes(vp); /* * Copy from inode table */ vap->va_fileid = ip->i_number; vap->va_mode = ip->i_mode & ~IFMT; vap->va_nlink = ip->i_nlink; vap->va_uid = ip->i_uid; vap->va_gid = ip->i_gid; vap->va_rdev = ip->i_rdev; vap->va_size = ip->i_size; vap->va_atime.tv_sec = ip->i_atime; vap->va_atime.tv_nsec = ip->i_atimensec; vap->va_mtime.tv_sec = ip->i_mtime; vap->va_mtime.tv_nsec = ip->i_mtimensec; vap->va_ctime.tv_sec = ip->i_ctime; vap->va_ctime.tv_nsec = ip->i_ctimensec; vap->va_flags = ip->i_flags; vap->va_gen = ip->i_gen; vap->va_blocksize = vp->v_mount->mnt_stat.f_iosize; vap->va_bytes = dbtob((u_quad_t)ip->i_blocks); vap->va_type = IFTOVT(ip->i_mode); vap->va_filerev = ip->i_modrev; return (0); } /* * Set attribute vnode op. called from several syscalls */ static int ext2_setattr(ap) struct vop_setattr_args /* { struct vnode *a_vp; struct vattr *a_vap; struct ucred *a_cred; struct thread *a_td; } */ *ap; { struct vattr *vap = ap->a_vap; struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); struct ucred *cred = ap->a_cred; struct thread *td = ap->a_td; int error; /* * Check for unsettable attributes. */ if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { return (EINVAL); } if (vap->va_flags != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); /* * Callers may only modify the file flags on objects they * have VADMIN rights for. */ if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) return (error); /* * Unprivileged processes and privileged processes in * jail() are not permitted to unset system flags, or * modify flags if any system flags are set. * Privileged non-jail processes may not modify system flags * if securelevel > 0 and any existing system flags are set. */ if (!suser_cred(cred, SUSER_ALLOWJAIL)) { if (ip->i_flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) { error = securelevel_gt(cred, 0); if (error) return (error); } ip->i_flags = vap->va_flags; } else { if (ip->i_flags & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND) || (vap->va_flags & UF_SETTABLE) != vap->va_flags) return (EPERM); ip->i_flags &= SF_SETTABLE; ip->i_flags |= (vap->va_flags & UF_SETTABLE); } ip->i_flag |= IN_CHANGE; if (vap->va_flags & (IMMUTABLE | APPEND)) return (0); } if (ip->i_flags & (IMMUTABLE | APPEND)) return (EPERM); /* * Go through the fields and update iff not VNOVAL. */ if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if ((error = ext2_chown(vp, vap->va_uid, vap->va_gid, cred, td)) != 0) return (error); } if (vap->va_size != VNOVAL) { /* * Disallow write attempts on read-only file systems; * unless the file is a socket, fifo, or a block or * character device resident on the file system. */ switch (vp->v_type) { case VDIR: return (EISDIR); case VLNK: case VREG: if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); break; default: break; } if ((error = ext2_truncate(vp, vap->va_size, 0, cred, td)) != 0) return (error); } if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); /* * From utimes(2): * If times is NULL, ... The caller must be the owner of * the file, have permission to write the file, or be the * super-user. * If times is non-NULL, ... The caller must be the owner of * the file or be the super-user. */ if ((error = VOP_ACCESS(vp, VADMIN, cred, td)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_ACCESS(vp, VWRITE, cred, td)))) return (error); if (vap->va_atime.tv_sec != VNOVAL) ip->i_flag |= IN_ACCESS; if (vap->va_mtime.tv_sec != VNOVAL) ip->i_flag |= IN_CHANGE | IN_UPDATE; ext2_itimes(vp); if (vap->va_atime.tv_sec != VNOVAL) { ip->i_atime = vap->va_atime.tv_sec; ip->i_atimensec = vap->va_atime.tv_nsec; } if (vap->va_mtime.tv_sec != VNOVAL) { ip->i_mtime = vap->va_mtime.tv_sec; ip->i_mtimensec = vap->va_mtime.tv_nsec; } error = ext2_update(vp, 0); if (error) return (error); } error = 0; if (vap->va_mode != (mode_t)VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); error = ext2_chmod(vp, (int)vap->va_mode, cred, td); } return (error); } /* * Change the mode on a file. * Inode must be locked before calling. */ static int ext2_chmod(vp, mode, cred, td) struct vnode *vp; int mode; struct ucred *cred; struct thread *td; { struct inode *ip = VTOI(vp); int error; /* * To modify the permissions on a file, must possess VADMIN * for that file. */ if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) return (error); /* * Privileged processes may set the sticky bit on non-directories, * as well as set the setgid bit on a file with a group that the * process is not a member of. */ if (suser_cred(cred, SUSER_ALLOWJAIL)) { if (vp->v_type != VDIR && (mode & S_ISTXT)) return (EFTYPE); if (!groupmember(ip->i_gid, cred) && (mode & ISGID)) return (EPERM); } ip->i_mode &= ~ALLPERMS; ip->i_mode |= (mode & ALLPERMS); ip->i_flag |= IN_CHANGE; return (0); } /* * Perform chown operation on inode ip; * inode must be locked prior to call. */ static int ext2_chown(vp, uid, gid, cred, td) struct vnode *vp; uid_t uid; gid_t gid; struct ucred *cred; struct thread *td; { struct inode *ip = VTOI(vp); uid_t ouid; gid_t ogid; int error = 0; if (uid == (uid_t)VNOVAL) uid = ip->i_uid; if (gid == (gid_t)VNOVAL) gid = ip->i_gid; /* * To modify the ownership of a file, must possess VADMIN * for that file. */ if ((error = VOP_ACCESS(vp, VADMIN, cred, td))) return (error); /* * To change the owner of a file, or change the group of a file * to a group of which we are not a member, the caller must * have privilege. */ if ((uid != ip->i_uid || (gid != ip->i_gid && !groupmember(gid, cred))) && (error = suser_cred(cred, SUSER_ALLOWJAIL))) return (error); ogid = ip->i_gid; ouid = ip->i_uid; ip->i_gid = gid; ip->i_uid = uid; ip->i_flag |= IN_CHANGE; if (suser_cred(cred, SUSER_ALLOWJAIL) && (ouid != uid || ogid != gid)) ip->i_mode &= ~(ISUID | ISGID); return (0); } /* * Synch an open file. */ /* ARGSUSED */ static int ext2_fsync(ap) struct vop_fsync_args /* { struct vnode *a_vp; struct ucred *a_cred; int a_waitfor; struct thread *a_td; } */ *ap; { /* * Flush all dirty buffers associated with a vnode. */ ext2_discard_prealloc(VTOI(ap->a_vp)); vop_stdfsync(ap); return (ext2_update(ap->a_vp, ap->a_waitfor == MNT_WAIT)); } /* * Mknod vnode call */ /* ARGSUSED */ static int ext2_mknod(ap) struct vop_mknod_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; } */ *ap; { struct vattr *vap = ap->a_vap; struct vnode **vpp = ap->a_vpp; struct inode *ip; ino_t ino; int error; error = ext2_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), ap->a_dvp, vpp, ap->a_cnp); if (error) return (error); ip = VTOI(*vpp); ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; if (vap->va_rdev != VNOVAL) { /* * Want to be able to use this to make badblock * inodes, so don't truncate the dev number. */ ip->i_rdev = vap->va_rdev; } /* * Remove inode, then reload it through VFS_VGET so it is * checked to see if it is an alias of an existing entry in * the inode cache. XXX I don't believe this is necessary now. */ (*vpp)->v_type = VNON; ino = ip->i_number; /* Save this before vgone() invalidates ip. */ vgone(*vpp); vput(*vpp); error = VFS_VGET(ap->a_dvp->v_mount, ino, LK_EXCLUSIVE, vpp); if (error) { *vpp = NULL; return (error); } return (0); } static int ext2_remove(ap) struct vop_remove_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; } */ *ap; { struct inode *ip; struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; int error; ip = VTOI(vp); if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || (VTOI(dvp)->i_flags & APPEND)) { error = EPERM; goto out; } error = ext2_dirremove(dvp, ap->a_cnp); if (error == 0) { ip->i_nlink--; ip->i_flag |= IN_CHANGE; } out: return (error); } /* * link vnode call */ static int ext2_link(ap) struct vop_link_args /* { struct vnode *a_tdvp; struct vnode *a_vp; struct componentname *a_cnp; } */ *ap; { struct vnode *vp = ap->a_vp; struct vnode *tdvp = ap->a_tdvp; struct componentname *cnp = ap->a_cnp; struct inode *ip; int error; #ifdef DIAGNOSTIC if ((cnp->cn_flags & HASBUF) == 0) panic("ext2_link: no name"); #endif if (tdvp->v_mount != vp->v_mount) { error = EXDEV; goto out; } ip = VTOI(vp); if ((nlink_t)ip->i_nlink >= LINK_MAX) { error = EMLINK; goto out; } if (ip->i_flags & (IMMUTABLE | APPEND)) { error = EPERM; goto out; } ip->i_nlink++; ip->i_flag |= IN_CHANGE; error = ext2_update(vp, 1); if (!error) error = ext2_direnter(ip, tdvp, cnp); if (error) { ip->i_nlink--; ip->i_flag |= IN_CHANGE; } out: return (error); } /* * Rename system call. * See comments in sys/ufs/ufs/ufs_vnops.c */ static int ext2_rename(ap) struct vop_rename_args /* { struct vnode *a_fdvp; struct vnode *a_fvp; struct componentname *a_fcnp; struct vnode *a_tdvp; struct vnode *a_tvp; struct componentname *a_tcnp; } */ *ap; { struct vnode *tvp = ap->a_tvp; struct vnode *tdvp = ap->a_tdvp; struct vnode *fvp = ap->a_fvp; struct vnode *fdvp = ap->a_fdvp; struct componentname *tcnp = ap->a_tcnp; struct componentname *fcnp = ap->a_fcnp; struct thread *td = fcnp->cn_thread; struct inode *ip, *xp, *dp; struct dirtemplate dirbuf; int doingdirectory = 0, oldparent = 0, newparent = 0; int error = 0; u_char namlen; #ifdef DIAGNOSTIC if ((tcnp->cn_flags & HASBUF) == 0 || (fcnp->cn_flags & HASBUF) == 0) panic("ext2_rename: no name"); #endif /* * Check for cross-device rename. */ if ((fvp->v_mount != tdvp->v_mount) || (tvp && (fvp->v_mount != tvp->v_mount))) { error = EXDEV; abortit: if (tdvp == tvp) vrele(tdvp); else vput(tdvp); if (tvp) vput(tvp); vrele(fdvp); vrele(fvp); return (error); } if (tvp && ((VTOI(tvp)->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || (VTOI(tdvp)->i_flags & APPEND))) { error = EPERM; goto abortit; } /* * Renaming a file to itself has no effect. The upper layers should * not call us in that case. Temporarily just warn if they do. */ if (fvp == tvp) { printf("ext2_rename: fvp == tvp (can't happen)\n"); error = 0; goto abortit; } if ((error = vn_lock(fvp, LK_EXCLUSIVE, td)) != 0) goto abortit; dp = VTOI(fdvp); ip = VTOI(fvp); if (ip->i_nlink >= LINK_MAX) { VOP_UNLOCK(fvp, 0, td); error = EMLINK; goto abortit; } if ((ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND)) || (dp->i_flags & APPEND)) { VOP_UNLOCK(fvp, 0, td); error = EPERM; goto abortit; } if ((ip->i_mode & IFMT) == IFDIR) { /* * Avoid ".", "..", and aliases of "." for obvious reasons. */ if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.') || dp == ip || (fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT || (ip->i_flag & IN_RENAME)) { VOP_UNLOCK(fvp, 0, td); error = EINVAL; goto abortit; } ip->i_flag |= IN_RENAME; oldparent = dp->i_number; doingdirectory++; } vrele(fdvp); /* * When the target exists, both the directory * and target vnodes are returned locked. */ dp = VTOI(tdvp); xp = NULL; if (tvp) xp = VTOI(tvp); /* * 1) Bump link count while we're moving stuff * around. If we crash somewhere before * completing our work, the link count * may be wrong, but correctable. */ ip->i_nlink++; ip->i_flag |= IN_CHANGE; if ((error = ext2_update(fvp, 1)) != 0) { VOP_UNLOCK(fvp, 0, td); goto bad; } /* * If ".." must be changed (ie the directory gets a new * parent) then the source directory must not be in the * directory heirarchy above the target, as this would * orphan everything below the source directory. Also * the user must have write permission in the source so * as to be able to change "..". We must repeat the call * to namei, as the parent directory is unlocked by the * call to checkpath(). */ error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread); VOP_UNLOCK(fvp, 0, td); if (oldparent != dp->i_number) newparent = dp->i_number; if (doingdirectory && newparent) { if (error) /* write access check above */ goto bad; if (xp != NULL) vput(tvp); error = ext2_checkpath(ip, dp, tcnp->cn_cred); if (error) goto out; VREF(tdvp); error = relookup(tdvp, &tvp, tcnp); if (error) goto out; vrele(tdvp); dp = VTOI(tdvp); xp = NULL; if (tvp) xp = VTOI(tvp); } /* * 2) If target doesn't exist, link the target * to the source and unlink the source. * Otherwise, rewrite the target directory * entry to reference the source inode and * expunge the original entry's existence. */ if (xp == NULL) { if (dp->i_devvp != ip->i_devvp) panic("ext2_rename: EXDEV"); /* * Account for ".." in new directory. * When source and destination have the same * parent we don't fool with the link count. */ if (doingdirectory && newparent) { if ((nlink_t)dp->i_nlink >= LINK_MAX) { error = EMLINK; goto bad; } dp->i_nlink++; dp->i_flag |= IN_CHANGE; error = ext2_update(tdvp, 1); if (error) goto bad; } error = ext2_direnter(ip, tdvp, tcnp); if (error) { if (doingdirectory && newparent) { dp->i_nlink--; dp->i_flag |= IN_CHANGE; (void)ext2_update(tdvp, 1); } goto bad; } vput(tdvp); } else { if (xp->i_devvp != dp->i_devvp || xp->i_devvp != ip->i_devvp) panic("ext2_rename: EXDEV"); /* * Short circuit rename(foo, foo). */ if (xp->i_number == ip->i_number) panic("ext2_rename: same file"); /* * If the parent directory is "sticky", then the user must * own the parent directory, or the destination of the rename, * otherwise the destination may not be changed (except by * root). This implements append-only directories. */ if ((dp->i_mode & S_ISTXT) && tcnp->cn_cred->cr_uid != 0 && tcnp->cn_cred->cr_uid != dp->i_uid && xp->i_uid != tcnp->cn_cred->cr_uid) { error = EPERM; goto bad; } /* * Target must be empty if a directory and have no links * to it. Also, ensure source and target are compatible * (both directories, or both not directories). */ if ((xp->i_mode&IFMT) == IFDIR) { if (! ext2_dirempty(xp, dp->i_number, tcnp->cn_cred) || xp->i_nlink > 2) { error = ENOTEMPTY; goto bad; } if (!doingdirectory) { error = ENOTDIR; goto bad; } cache_purge(tdvp); } else if (doingdirectory) { error = EISDIR; goto bad; } error = ext2_dirrewrite(dp, ip, tcnp); if (error) goto bad; /* * If the target directory is in the same * directory as the source directory, * decrement the link count on the parent * of the target directory. */ if (doingdirectory && !newparent) { dp->i_nlink--; dp->i_flag |= IN_CHANGE; } vput(tdvp); /* * Adjust the link count of the target to * reflect the dirrewrite above. If this is * a directory it is empty and there are * no links to it, so we can squash the inode and * any space associated with it. We disallowed * renaming over top of a directory with links to * it above, as the remaining link would point to * a directory without "." or ".." entries. */ xp->i_nlink--; if (doingdirectory) { if (--xp->i_nlink != 0) panic("ext2_rename: linked directory"); error = ext2_truncate(tvp, (off_t)0, IO_SYNC, tcnp->cn_cred, tcnp->cn_thread); } xp->i_flag |= IN_CHANGE; vput(tvp); xp = NULL; } /* * 3) Unlink the source. */ fcnp->cn_flags &= ~MODMASK; fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; VREF(fdvp); error = relookup(fdvp, &fvp, fcnp); if (error == 0) vrele(fdvp); if (fvp != NULL) { xp = VTOI(fvp); dp = VTOI(fdvp); } else { /* * From name has disappeared. */ if (doingdirectory) panic("ext2_rename: lost dir entry"); vrele(ap->a_fvp); return (0); } /* * Ensure that the directory entry still exists and has not * changed while the new name has been entered. If the source is * a file then the entry may have been unlinked or renamed. In * either case there is no further work to be done. If the source * is a directory then it cannot have been rmdir'ed; its link * count of three would cause a rmdir to fail with ENOTEMPTY. * The IN_RENAME flag ensures that it cannot be moved by another * rename. */ if (xp != ip) { if (doingdirectory) panic("ext2_rename: lost dir entry"); } else { /* * If the source is a directory with a * new parent, the link count of the old * parent directory must be decremented * and ".." set to point to the new parent. */ if (doingdirectory && newparent) { dp->i_nlink--; dp->i_flag |= IN_CHANGE; error = vn_rdwr(UIO_READ, fvp, (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, tcnp->cn_cred, NOCRED, (int *)0, (struct thread *)0); if (error == 0) { /* Like ufs little-endian: */ namlen = dirbuf.dotdot_type; if (namlen != 2 || dirbuf.dotdot_name[0] != '.' || dirbuf.dotdot_name[1] != '.') { ext2_dirbad(xp, (doff_t)12, "rename: mangled dir"); } else { dirbuf.dotdot_ino = newparent; (void) vn_rdwr(UIO_WRITE, fvp, (caddr_t)&dirbuf, sizeof (struct dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_SYNC | IO_NOMACCHECK, tcnp->cn_cred, NOCRED, (int *)0, (struct thread *)0); cache_purge(fdvp); } } } error = ext2_dirremove(fdvp, fcnp); if (!error) { xp->i_nlink--; xp->i_flag |= IN_CHANGE; } xp->i_flag &= ~IN_RENAME; } if (dp) vput(fdvp); if (xp) vput(fvp); vrele(ap->a_fvp); return (error); bad: if (xp) vput(ITOV(xp)); vput(ITOV(dp)); out: if (doingdirectory) ip->i_flag &= ~IN_RENAME; if (vn_lock(fvp, LK_EXCLUSIVE, td) == 0) { ip->i_nlink--; ip->i_flag |= IN_CHANGE; ip->i_flag &= ~IN_RENAME; vput(fvp); } else vrele(fvp); return (error); } /* * Mkdir system call */ static int ext2_mkdir(ap) struct vop_mkdir_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; } */ *ap; { struct vnode *dvp = ap->a_dvp; struct vattr *vap = ap->a_vap; struct componentname *cnp = ap->a_cnp; struct inode *ip, *dp; struct vnode *tvp; struct dirtemplate dirtemplate, *dtp; int error, dmode; #ifdef DIAGNOSTIC if ((cnp->cn_flags & HASBUF) == 0) panic("ext2_mkdir: no name"); #endif dp = VTOI(dvp); if ((nlink_t)dp->i_nlink >= LINK_MAX) { error = EMLINK; goto out; } dmode = vap->va_mode & 0777; dmode |= IFDIR; /* * Must simulate part of ext2_makeinode here to acquire the inode, * but not have it entered in the parent directory. The entry is * made later after writing "." and ".." entries. */ error = ext2_valloc(dvp, dmode, cnp->cn_cred, &tvp); if (error) goto out; ip = VTOI(tvp); ip->i_gid = dp->i_gid; #ifdef SUIDDIR { /* * if we are hacking owners here, (only do this where told to) * and we are not giving it TOO root, (would subvert quotas) * then go ahead and give it to the other user. * The new directory also inherits the SUID bit. * If user's UID and dir UID are the same, * 'give it away' so that the SUID is still forced on. */ if ( (dvp->v_mount->mnt_flag & MNT_SUIDDIR) && (dp->i_mode & ISUID) && dp->i_uid) { dmode |= ISUID; ip->i_uid = dp->i_uid; } else { ip->i_uid = cnp->cn_cred->cr_uid; } } #else ip->i_uid = cnp->cn_cred->cr_uid; #endif ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; ip->i_mode = dmode; tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */ ip->i_nlink = 2; if (cnp->cn_flags & ISWHITEOUT) ip->i_flags |= UF_OPAQUE; error = ext2_update(tvp, 1); /* * Bump link count in parent directory * to reflect work done below. Should * be done before reference is created * so reparation is possible if we crash. */ dp->i_nlink++; dp->i_flag |= IN_CHANGE; error = ext2_update(dvp, 1); if (error) goto bad; /* Initialize directory with "." and ".." from static template. */ if (EXT2_HAS_INCOMPAT_FEATURE(ip->i_e2fs->s_es, EXT2_FEATURE_INCOMPAT_FILETYPE)) dtp = &mastertemplate; else dtp = &omastertemplate; dirtemplate = *dtp; dirtemplate.dot_ino = ip->i_number; dirtemplate.dotdot_ino = dp->i_number; /* note that in ext2 DIRBLKSIZ == blocksize, not DEV_BSIZE * so let's just redefine it - for this function only */ #undef DIRBLKSIZ #define DIRBLKSIZ VTOI(dvp)->i_e2fs->s_blocksize dirtemplate.dotdot_reclen = DIRBLKSIZ - 12; error = vn_rdwr(UIO_WRITE, tvp, (caddr_t)&dirtemplate, sizeof (dirtemplate), (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_SYNC | IO_NOMACCHECK, cnp->cn_cred, NOCRED, (int *)0, (struct thread *)0); if (error) { dp->i_nlink--; dp->i_flag |= IN_CHANGE; goto bad; } if (DIRBLKSIZ > VFSTOEXT2(dvp->v_mount)->um_mountp->mnt_stat.f_bsize) /* XXX should grow with balloc() */ panic("ext2_mkdir: blksize"); else { ip->i_size = DIRBLKSIZ; ip->i_flag |= IN_CHANGE; } /* Directory set up, now install its entry in the parent directory. */ error = ext2_direnter(ip, dvp, cnp); if (error) { dp->i_nlink--; dp->i_flag |= IN_CHANGE; } bad: /* * No need to do an explicit VOP_TRUNCATE here, vrele will do this * for us because we set the link count to 0. */ if (error) { ip->i_nlink = 0; ip->i_flag |= IN_CHANGE; vput(tvp); } else *ap->a_vpp = tvp; out: return (error); #undef DIRBLKSIZ #define DIRBLKSIZ DEV_BSIZE } /* * Rmdir system call. */ static int ext2_rmdir(ap) struct vop_rmdir_args /* { struct vnode *a_dvp; struct vnode *a_vp; struct componentname *a_cnp; } */ *ap; { struct vnode *vp = ap->a_vp; struct vnode *dvp = ap->a_dvp; struct componentname *cnp = ap->a_cnp; struct thread *td = cnp->cn_thread; struct inode *ip, *dp; int error; ip = VTOI(vp); dp = VTOI(dvp); /* * Verify the directory is empty (and valid). * (Rmdir ".." won't be valid since * ".." will contain a reference to * the current directory and thus be * non-empty.) */ error = 0; if (ip->i_nlink != 2 || !ext2_dirempty(ip, dp->i_number, cnp->cn_cred)) { error = ENOTEMPTY; goto out; } if ((dp->i_flags & APPEND) || (ip->i_flags & (NOUNLINK | IMMUTABLE | APPEND))) { error = EPERM; goto out; } /* * Delete reference to directory before purging * inode. If we crash in between, the directory * will be reattached to lost+found, */ error = ext2_dirremove(dvp, cnp); if (error) goto out; dp->i_nlink--; dp->i_flag |= IN_CHANGE; cache_purge(dvp); VOP_UNLOCK(dvp, 0, td); /* * Truncate inode. The only stuff left * in the directory is "." and "..". The * "." reference is inconsequential since * we're quashing it. The ".." reference * has already been adjusted above. We've * removed the "." reference and the reference * in the parent directory, but there may be * other hard links so decrement by 2 and * worry about them later. */ ip->i_nlink -= 2; error = ext2_truncate(vp, (off_t)0, IO_SYNC, cnp->cn_cred, td); cache_purge(ITOV(ip)); vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); out: return (error); } /* * symlink -- make a symbolic link */ static int ext2_symlink(ap) struct vop_symlink_args /* { struct vnode *a_dvp; struct vnode **a_vpp; struct componentname *a_cnp; struct vattr *a_vap; char *a_target; } */ *ap; { struct vnode *vp, **vpp = ap->a_vpp; struct inode *ip; int len, error; error = ext2_makeinode(IFLNK | ap->a_vap->va_mode, ap->a_dvp, vpp, ap->a_cnp); if (error) return (error); vp = *vpp; len = strlen(ap->a_target); if (len < vp->v_mount->mnt_maxsymlinklen) { ip = VTOI(vp); bcopy(ap->a_target, (char *)ip->i_shortlink, len); ip->i_size = len; ip->i_flag |= IN_CHANGE | IN_UPDATE; } else error = vn_rdwr(UIO_WRITE, vp, ap->a_target, len, (off_t)0, UIO_SYSSPACE, IO_NODELOCKED | IO_NOMACCHECK, ap->a_cnp->cn_cred, NOCRED, (int *)0, (struct thread *)0); if (error) vput(vp); return (error); } /* * Return target name of a symbolic link */ static int ext2_readlink(ap) struct vop_readlink_args /* { struct vnode *a_vp; struct uio *a_uio; struct ucred *a_cred; } */ *ap; { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); int isize; isize = ip->i_size; if (isize < vp->v_mount->mnt_maxsymlinklen) { uiomove((char *)ip->i_shortlink, isize, ap->a_uio); return (0); } return (VOP_READ(vp, ap->a_uio, 0, ap->a_cred)); } /* * Calculate the logical to physical mapping if not done already, * then call the device strategy routine. * * In order to be able to swap to a file, the ext2_bmaparray() operation may not * deadlock on memory. See ext2_bmap() for details. */ static int ext2_strategy(ap) struct vop_strategy_args /* { struct vnode *a_vp; struct buf *a_bp; } */ *ap; { struct buf *bp = ap->a_bp; struct vnode *vp = ap->a_vp; struct inode *ip; struct bufobj *bo; int32_t blkno; int error; ip = VTOI(vp); if (vp->v_type == VBLK || vp->v_type == VCHR) panic("ext2_strategy: spec"); if (bp->b_blkno == bp->b_lblkno) { error = ext2_bmaparray(vp, bp->b_lblkno, &blkno, NULL, NULL); bp->b_blkno = blkno; if (error) { bp->b_error = error; bp->b_ioflags |= BIO_ERROR; bufdone(bp); return (error); } if ((long)bp->b_blkno == -1) vfs_bio_clrbuf(bp); } if ((long)bp->b_blkno == -1) { bufdone(bp); return (0); } bp->b_iooffset = dbtob(bp->b_blkno); bo = VFSTOEXT2(vp->v_mount)->um_bo; BO_STRATEGY(bo, bp); return (0); } /* * Print out the contents of an inode. */ static int ext2_print(ap) struct vop_print_args /* { struct vnode *a_vp; } */ *ap; { struct vnode *vp = ap->a_vp; struct inode *ip = VTOI(vp); vn_printf(ip->i_devvp, "\tino %lu", (u_long)ip->i_number); if (vp->v_type == VFIFO) fifo_printinfo(vp); printf("\n"); return (0); } /* * Close wrapper for fifos. * * Update the times on the inode then do device close. */ static int ext2fifo_close(ap) struct vop_close_args /* { struct vnode *a_vp; int a_fflag; struct ucred *a_cred; struct thread *a_td; } */ *ap; { struct vnode *vp = ap->a_vp; VI_LOCK(vp); if (vp->v_usecount > 1) ext2_itimes(vp); VI_UNLOCK(vp); return (fifo_specops.vop_close(ap)); } /* * Kqfilter wrapper for fifos. * * Fall through to ext2 kqfilter routines if needed */ static int ext2fifo_kqfilter(ap) struct vop_kqfilter_args *ap; { int error; error = fifo_specops.vop_kqfilter(ap); if (error) error = ext2_kqfilter(ap); return (error); } /* * Return POSIX pathconf information applicable to ext2 filesystems. */ static int ext2_pathconf(ap) struct vop_pathconf_args /* { struct vnode *a_vp; int a_name; int *a_retval; } */ *ap; { switch (ap->a_name) { case _PC_LINK_MAX: *ap->a_retval = LINK_MAX; return (0); case _PC_NAME_MAX: *ap->a_retval = NAME_MAX; return (0); case _PC_PATH_MAX: *ap->a_retval = PATH_MAX; return (0); case _PC_PIPE_BUF: *ap->a_retval = PIPE_BUF; return (0); case _PC_CHOWN_RESTRICTED: *ap->a_retval = 1; return (0); case _PC_NO_TRUNC: *ap->a_retval = 1; return (0); default: return (EINVAL); } /* NOTREACHED */ } /* * Advisory record locking support */ static int ext2_advlock(ap) struct vop_advlock_args /* { struct vnode *a_vp; caddr_t a_id; int a_op; struct flock *a_fl; int a_flags; } */ *ap; { struct inode *ip = VTOI(ap->a_vp); return (lf_advlock(ap, &(ip->i_lockf), ip->i_size)); } /* * Initialize the vnode associated with a new inode, handle aliased * vnodes. */ int ext2_vinit(mntp, fifoops, vpp) struct mount *mntp; struct vop_vector *fifoops; struct vnode **vpp; { struct inode *ip; struct vnode *vp; vp = *vpp; ip = VTOI(vp); vp->v_type = IFTOVT(ip->i_mode); if (vp->v_type == VFIFO) vp->v_op = fifoops; if (ip->i_number == ROOTINO) vp->v_vflag |= VV_ROOT; ip->i_modrev = init_va_filerev(); *vpp = vp; return (0); } /* * Allocate a new inode. */ static int ext2_makeinode(mode, dvp, vpp, cnp) int mode; struct vnode *dvp; struct vnode **vpp; struct componentname *cnp; { struct inode *ip, *pdir; struct vnode *tvp; int error; pdir = VTOI(dvp); #ifdef DIAGNOSTIC if ((cnp->cn_flags & HASBUF) == 0) panic("ext2_makeinode: no name"); #endif *vpp = NULL; if ((mode & IFMT) == 0) mode |= IFREG; error = ext2_valloc(dvp, mode, cnp->cn_cred, &tvp); if (error) { return (error); } ip = VTOI(tvp); ip->i_gid = pdir->i_gid; #ifdef SUIDDIR { /* * if we are * not the owner of the directory, * and we are hacking owners here, (only do this where told to) * and we are not giving it TOO root, (would subvert quotas) * then go ahead and give it to the other user. * Note that this drops off the execute bits for security. */ if ( (dvp->v_mount->mnt_flag & MNT_SUIDDIR) && (pdir->i_mode & ISUID) && (pdir->i_uid != cnp->cn_cred->cr_uid) && pdir->i_uid) { ip->i_uid = pdir->i_uid; mode &= ~07111; } else { ip->i_uid = cnp->cn_cred->cr_uid; } } #else ip->i_uid = cnp->cn_cred->cr_uid; #endif ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; ip->i_mode = mode; tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ ip->i_nlink = 1; if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && suser_cred(cnp->cn_cred, SUSER_ALLOWJAIL)) ip->i_mode &= ~ISGID; if (cnp->cn_flags & ISWHITEOUT) ip->i_flags |= UF_OPAQUE; /* * Make sure inode goes to disk before directory entry. */ error = ext2_update(tvp, 1); if (error) goto bad; error = ext2_direnter(ip, dvp, cnp); if (error) goto bad; *vpp = tvp; return (0); bad: /* * Write error occurred trying to update the inode * or the directory so must deallocate the inode. */ ip->i_nlink = 0; ip->i_flag |= IN_CHANGE; vput(tvp); return (error); } static struct filterops ext2read_filtops = { 1, NULL, filt_ext2detach, filt_ext2read }; static struct filterops ext2write_filtops = { 1, NULL, filt_ext2detach, filt_ext2write }; static struct filterops ext2vnode_filtops = { 1, NULL, filt_ext2detach, filt_ext2vnode }; static int ext2_kqfilter(ap) struct vop_kqfilter_args /* { struct vnode *a_vp; struct knote *a_kn; } */ *ap; { struct vnode *vp = ap->a_vp; struct knote *kn = ap->a_kn; switch (kn->kn_filter) { case EVFILT_READ: kn->kn_fop = &ext2read_filtops; break; case EVFILT_WRITE: kn->kn_fop = &ext2write_filtops; break; case EVFILT_VNODE: kn->kn_fop = &ext2vnode_filtops; break; default: return (1); } kn->kn_hook = (caddr_t)vp; if (vp->v_pollinfo == NULL) v_addpollinfo(vp); if (vp->v_pollinfo == NULL) return ENOMEM; knlist_add(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0); return (0); } static void filt_ext2detach(struct knote *kn) { struct vnode *vp = (struct vnode *)kn->kn_hook; KASSERT(vp->v_pollinfo != NULL, ("Mising v_pollinfo")); knlist_remove(&vp->v_pollinfo->vpi_selinfo.si_note, kn, 0); } /*ARGSUSED*/ static int filt_ext2read(struct knote *kn, long hint) { struct vnode *vp = (struct vnode *)kn->kn_hook; struct inode *ip = VTOI(vp); /* * filesystem is gone, so set the EOF flag and schedule * the knote for deletion. */ if (hint == NOTE_REVOKE) { kn->kn_flags |= (EV_EOF | EV_ONESHOT); return (1); } kn->kn_data = ip->i_size - kn->kn_fp->f_offset; return (kn->kn_data != 0); } /*ARGSUSED*/ static int filt_ext2write(struct knote *kn, long hint) { /* * filesystem is gone, so set the EOF flag and schedule * the knote for deletion. */ if (hint == NOTE_REVOKE) kn->kn_flags |= (EV_EOF | EV_ONESHOT); kn->kn_data = 0; return (1); } static int filt_ext2vnode(struct knote *kn, long hint) { if (kn->kn_sfflags & hint) kn->kn_fflags |= hint; if (hint == NOTE_REVOKE) { kn->kn_flags |= EV_EOF; return (1); } return (kn->kn_fflags != 0); } diff --git a/sys/gnu/reiserfs/reiserfs_fs.h b/sys/gnu/reiserfs/reiserfs_fs.h index e33c04eda0b5..5f88f0b339db 100644 --- a/sys/gnu/reiserfs/reiserfs_fs.h +++ b/sys/gnu/reiserfs/reiserfs_fs.h @@ -1,1298 +1,1298 @@ /*- * Copyright 2000 Hans Reiser * See README for licensing and copyright details * * Ported to FreeBSD by Jean-Sébastien Pédron * * $FreeBSD$ */ #ifndef _GNU_REISERFS_REISERFS_FS_H #define _GNU_REISERFS_REISERFS_FS_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #ifdef __i386__ -# include +# include #else -# include +# include #endif #include #include #include /* n must be power of 2 */ #define _ROUND_UP(x, n) (((x) + (n) - 1u) & ~((n) - 1u)) /* To be ok for alpha and others we have to align structures to 8 byte * boundary. */ #define ROUND_UP(x) _ROUND_UP(x, 8LL) /* ------------------------------------------------------------------- * Global variables * -------------------------------------------------------------------*/ extern struct vop_vector reiserfs_vnodeops; extern struct vop_vector reiserfs_specops; /* ------------------------------------------------------------------- * Super block * -------------------------------------------------------------------*/ #define REISERFS_BSIZE 1024 /* ReiserFS leaves the first 64k unused, so that partition labels have * enough space. If someone wants to write a fancy bootloader that needs * more than 64k, let us know, and this will be increased in size. * This number must be larger than than the largest block size on any * platform, or code will break. -Hans */ #define REISERFS_DISK_OFFSET 64 #define REISERFS_DISK_OFFSET_IN_BYTES \ ((REISERFS_DISK_OFFSET) * (REISERFS_BSIZE)) /* The spot for the super in versions 3.5 - 3.5.10 (inclusive) */ #define REISERFS_OLD_DISK_OFFSET 8 #define REISERFS_OLD_DISK_OFFSET_IN_BYTES \ ((REISERFS_OLD_DISK_OFFSET) * (REISERFS_BSIZE)) /* * Structure of a super block on disk, a version of which in RAM is * often accessed as REISERFS_SB(s)->r_rs. The version in RAM is part of * a larger structure containing fields never written to disk. */ #define UNSET_HASH 0 /* read_super will guess about, what hash names in directories were sorted with */ #define TEA_HASH 1 #define YURA_HASH 2 #define R5_HASH 3 #define DEFAULT_HASH R5_HASH struct journal_params { uint32_t jp_journal_1st_block; /* Where does journal start from on its device */ uint32_t jp_journal_dev; /* Journal device st_rdev */ uint32_t jp_journal_size; /* Size of the journal */ uint32_t jp_journal_trans_max; /* Max number of blocks in a transaction */ uint32_t jp_journal_magic; /* Random value made on fs creation (this was sb_journal_block_count) */ uint32_t jp_journal_max_batch; /* Max number of blocks to batch into a transaction */ uint32_t jp_journal_max_commit_age; /* In seconds, how old can an async commit be */ uint32_t jp_journal_max_trans_age; /* In seconds, how old a transaction be */ }; struct reiserfs_super_block_v1 { uint32_t s_block_count; /* Blocks count */ uint32_t s_free_blocks; /* Free blocks count */ uint32_t s_root_block; /* Root block number */ struct journal_params s_journal; uint16_t s_blocksize; uint16_t s_oid_maxsize; uint16_t s_oid_cursize; uint16_t s_umount_state; char s_magic[10]; uint16_t s_fs_state; uint32_t s_hash_function_code; uint16_t s_tree_height; uint16_t s_bmap_nr; uint16_t s_version; uint16_t s_reserved_for_journal; } __packed; #define SB_SIZE_V1 (sizeof(struct reiserfs_super_block_v1)) struct reiserfs_super_block { struct reiserfs_super_block_v1 s_v1; uint32_t s_inode_generation; uint32_t s_flags; unsigned char s_uuid[16]; unsigned char s_label[16]; char s_unused[88]; } __packed; #define SB_SIZE (sizeof(struct reiserfs_super_block)) #define REISERFS_VERSION_1 0 #define REISERFS_VERSION_2 2 #define REISERFS_SB(sbi) (sbi) #define SB_DISK_SUPER_BLOCK(sbi) (REISERFS_SB(sbi)->s_rs) #define SB_V1_DISK_SUPER_BLOCK(sbi) (&(SB_DISK_SUPER_BLOCK(sbi)->s_v1)) #define SB_BLOCKSIZE(sbi) \ le32toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_blocksize)) #define SB_BLOCK_COUNT(sbi) \ le32toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_block_count)) #define SB_FREE_BLOCKS(s) \ le32toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_free_blocks)) #define SB_REISERFS_MAGIC(sbi) \ (SB_V1_DISK_SUPER_BLOCK(sbi)->s_magic) #define SB_ROOT_BLOCK(sbi) \ le32toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_root_block)) #define SB_TREE_HEIGHT(sbi) \ le16toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_tree_height)) #define SB_REISERFS_STATE(sbi) \ le16toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_umount_state)) #define SB_VERSION(sbi) le16toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_version)) #define SB_BMAP_NR(sbi) le16toh((SB_V1_DISK_SUPER_BLOCK(sbi)->s_bmap_nr)) #define REISERFS_SUPER_MAGIC_STRING "ReIsErFs" #define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs" #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" extern const char reiserfs_3_5_magic_string[]; extern const char reiserfs_3_6_magic_string[]; extern const char reiserfs_jr_magic_string[]; int is_reiserfs_3_5(struct reiserfs_super_block *rs); int is_reiserfs_3_6(struct reiserfs_super_block *rs); int is_reiserfs_jr(struct reiserfs_super_block *rs); /* ReiserFS internal error code (used by search_by_key and fix_nodes) */ #define IO_ERROR -2 typedef uint32_t b_blocknr_t; typedef uint32_t unp_t; struct unfm_nodeinfo { unp_t unfm_nodenum; unsigned short unfm_freespace; }; /* There are two formats of keys: 3.5 and 3.6 */ #define KEY_FORMAT_3_5 0 #define KEY_FORMAT_3_6 1 /* There are two stat datas */ #define STAT_DATA_V1 0 #define STAT_DATA_V2 1 #define REISERFS_I(ip) (ip) #define get_inode_item_key_version(ip) \ ((REISERFS_I(ip)->i_flags & i_item_key_version_mask) ? \ KEY_FORMAT_3_6 : KEY_FORMAT_3_5) #define set_inode_item_key_version(ip, version) ({ \ if ((version) == KEY_FORMAT_3_6) \ REISERFS_I(ip)->i_flags |= i_item_key_version_mask; \ else \ REISERFS_I(ip)->i_flags &= ~i_item_key_version_mask; \ }) #define get_inode_sd_version(ip) \ ((REISERFS_I(ip)->i_flags & i_stat_data_version_mask) ? \ STAT_DATA_V2 : STAT_DATA_V1) #define set_inode_sd_version(inode, version) ({ \ if((version) == STAT_DATA_V2) \ REISERFS_I(ip)->i_flags |= i_stat_data_version_mask; \ else \ REISERFS_I(ip)->i_flags &= ~i_stat_data_version_mask; \ }) /* Values for s_umount_state field */ #define REISERFS_VALID_FS 1 #define REISERFS_ERROR_FS 2 /* There are 5 item types currently */ #define TYPE_STAT_DATA 0 #define TYPE_INDIRECT 1 #define TYPE_DIRECT 2 #define TYPE_DIRENTRY 3 #define TYPE_MAXTYPE 3 #define TYPE_ANY 15 /* ------------------------------------------------------------------- * Key & item head * -------------------------------------------------------------------*/ struct offset_v1 { uint32_t k_offset; uint32_t k_uniqueness; } __packed; struct offset_v2 { #if BYTE_ORDER == LITTLE_ENDIAN /* little endian version */ uint64_t k_offset:60; uint64_t k_type:4; #else /* big endian version */ uint64_t k_type:4; uint64_t k_offset:60; #endif } __packed; #if (BYTE_ORDER == BIG_ENDIAN) typedef union { struct offset_v2 offset_v2; uint64_t linear; } __packed offset_v2_esafe_overlay; static inline uint16_t offset_v2_k_type(const struct offset_v2 *v2) { offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2; tmp.linear = le64toh(tmp.linear); return ((tmp.offset_v2.k_type <= TYPE_MAXTYPE) ? tmp.offset_v2.k_type : TYPE_ANY); } static inline void set_offset_v2_k_type(struct offset_v2 *v2, int type) { offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2; tmp->linear = le64toh(tmp->linear); tmp->offset_v2.k_type = type; tmp->linear = htole64(tmp->linear); } static inline off_t offset_v2_k_offset(const struct offset_v2 *v2) { offset_v2_esafe_overlay tmp = *(const offset_v2_esafe_overlay *)v2; tmp.linear = le64toh(tmp.linear); return (tmp.offset_v2.k_offset); } static inline void set_offset_v2_k_offset(struct offset_v2 *v2, off_t offset) { offset_v2_esafe_overlay *tmp = (offset_v2_esafe_overlay *)v2; tmp->linear = le64toh(tmp->linear); tmp->offset_v2.k_offset = offset; tmp->linear = htole64(tmp->linear); } #else /* BYTE_ORDER != BIG_ENDIAN */ #define offset_v2_k_type(v2) ((v2)->k_type) #define set_offset_v2_k_type(v2, val) (offset_v2_k_type(v2) = (val)) #define offset_v2_k_offset(v2) ((v2)->k_offset) #define set_offset_v2_k_offset(v2, val) (offset_v2_k_offset(v2) = (val)) #endif /* BYTE_ORDER == BIG_ENDIAN */ /* * Key of an item determines its location in the S+tree, and * is composed of 4 components */ struct key { uint32_t k_dir_id; /* Packing locality: by default parent directory object id */ uint32_t k_objectid; /* Object identifier */ union { struct offset_v1 k_offset_v1; struct offset_v2 k_offset_v2; } __packed u; } __packed; struct cpu_key { struct key on_disk_key; int version; int key_length; /* 3 in all cases but direct2indirect and indirect2direct conversion */ }; /* * Our function for comparing keys can compare keys of different * lengths. It takes as a parameter the length of the keys it is to * compare. These defines are used in determining what is to be passed * to it as that parameter. */ #define REISERFS_FULL_KEY_LEN 4 #define REISERFS_SHORT_KEY_LEN 2 #define KEY_SIZE (sizeof(struct key)) #define SHORT_KEY_SIZE (sizeof(uint32_t) + sizeof(uint32_t)) /* Return values for search_by_key and clones */ #define ITEM_FOUND 1 #define ITEM_NOT_FOUND 0 #define ENTRY_FOUND 1 #define ENTRY_NOT_FOUND 0 #define DIRECTORY_NOT_FOUND -1 #define REGULAR_FILE_FOUND -2 #define DIRECTORY_FOUND -3 #define BYTE_FOUND 1 #define BYTE_NOT_FOUND 0 #define FILE_NOT_FOUND -1 #define POSITION_FOUND 1 #define POSITION_NOT_FOUND 0 /* Return values for reiserfs_find_entry and search_by_entry_key */ #define NAME_FOUND 1 #define NAME_NOT_FOUND 0 #define GOTO_PREVIOUS_ITEM 2 #define NAME_FOUND_INVISIBLE 3 /* * Everything in the filesystem is stored as a set of items. The item * head contains the key of the item, its free space (for indirect * items) and specifies the location of the item itself within the * block. */ struct item_head { /* * Everything in the tree is found by searching for it based on * its key. */ struct key ih_key; union { /* * The free space in the last unformatted node of an * indirect item if this is an indirect item. This * equals 0xFFFF iff this is a direct item or stat data * item. Note that the key, not this field, is used to * determine the item type, and thus which field this * union contains. */ uint16_t ih_free_space_reserved; /* * If this is a directory item, this field equals the number of * directory entries in the directory item. */ uint16_t ih_entry_count; } __packed u; uint16_t ih_item_len; /* Total size of the item body */ uint16_t ih_item_location; /* An offset to the item body within the block */ uint16_t ih_version; /* 0 for all old items, 2 for new ones. Highest bit is set by fsck temporary, cleaned after all done */ } __packed; /* Size of item header */ #define IH_SIZE (sizeof(struct item_head)) #define ih_free_space(ih) le16toh((ih)->u.ih_free_space_reserved) #define ih_version(ih) le16toh((ih)->ih_version) #define ih_entry_count(ih) le16toh((ih)->u.ih_entry_count) #define ih_location(ih) le16toh((ih)->ih_item_location) #define ih_item_len(ih) le16toh((ih)->ih_item_len) /* * These operate on indirect items, where you've got an array of ints at * a possibly unaligned location. These are a noop on IA32. * * p is the array of uint32_t, i is the index into the array, v is the * value to store there. */ #define get_unaligned(ptr) \ ({ __typeof__(*(ptr)) __tmp; \ memcpy(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) #define put_unaligned(val, ptr) \ ({ __typeof__(*(ptr)) __tmp = (val); \ memcpy((ptr), &__tmp, sizeof(*(ptr))); \ (void)0; }) #define get_block_num(p, i) le32toh(get_unaligned((p) + (i))) #define put_block_num(p, i, v) put_unaligned(htole32(v), (p) + (i)) /* In old version uniqueness field shows key type */ #define V1_SD_UNIQUENESS 0 #define V1_INDIRECT_UNIQUENESS 0xfffffffe #define V1_DIRECT_UNIQUENESS 0xffffffff #define V1_DIRENTRY_UNIQUENESS 500 #define V1_ANY_UNIQUENESS 555 /* Here are conversion routines */ static inline int uniqueness2type(uint32_t uniqueness); static inline uint32_t type2uniqueness(int type); static inline int uniqueness2type(uint32_t uniqueness) { switch ((int)uniqueness) { case V1_SD_UNIQUENESS: return (TYPE_STAT_DATA); case V1_INDIRECT_UNIQUENESS: return (TYPE_INDIRECT); case V1_DIRECT_UNIQUENESS: return (TYPE_DIRECT); case V1_DIRENTRY_UNIQUENESS: return (TYPE_DIRENTRY); default: log(LOG_NOTICE, "reiserfs: unknown uniqueness (%u)\n", uniqueness); case V1_ANY_UNIQUENESS: return (TYPE_ANY); } } static inline uint32_t type2uniqueness(int type) { switch (type) { case TYPE_STAT_DATA: return (V1_SD_UNIQUENESS); case TYPE_INDIRECT: return (V1_INDIRECT_UNIQUENESS); case TYPE_DIRECT: return (V1_DIRECT_UNIQUENESS); case TYPE_DIRENTRY: return (V1_DIRENTRY_UNIQUENESS); default: log(LOG_NOTICE, "reiserfs: unknown type (%u)\n", type); case TYPE_ANY: return (V1_ANY_UNIQUENESS); } } /* * Key is pointer to on disk key which is stored in le, result is cpu, * there is no way to get version of object from key, so, provide * version to these defines. */ static inline off_t le_key_k_offset(int version, const struct key *key) { return ((version == KEY_FORMAT_3_5) ? le32toh(key->u.k_offset_v1.k_offset) : offset_v2_k_offset(&(key->u.k_offset_v2))); } static inline off_t le_ih_k_offset(const struct item_head *ih) { return (le_key_k_offset(ih_version(ih), &(ih->ih_key))); } static inline off_t le_key_k_type(int version, const struct key *key) { return ((version == KEY_FORMAT_3_5) ? uniqueness2type(le32toh(key->u.k_offset_v1.k_uniqueness)) : offset_v2_k_type(&(key->u.k_offset_v2))); } static inline off_t le_ih_k_type(const struct item_head *ih) { return (le_key_k_type(ih_version(ih), &(ih->ih_key))); } static inline void set_le_key_k_offset(int version, struct key *key, off_t offset) { (version == KEY_FORMAT_3_5) ? (key->u.k_offset_v1.k_offset = htole32(offset)) : (set_offset_v2_k_offset(&(key->u.k_offset_v2), offset)); } static inline void set_le_ih_k_offset(struct item_head *ih, off_t offset) { set_le_key_k_offset(ih_version(ih), &(ih->ih_key), offset); } static inline void set_le_key_k_type(int version, struct key *key, int type) { (version == KEY_FORMAT_3_5) ? (key->u.k_offset_v1.k_uniqueness = htole32(type2uniqueness(type))) : (set_offset_v2_k_type(&(key->u.k_offset_v2), type)); } static inline void set_le_ih_k_type(struct item_head *ih, int type) { set_le_key_k_type(ih_version(ih), &(ih->ih_key), type); } #define is_direntry_le_key(version, key) \ (le_key_k_type(version, key) == TYPE_DIRENTRY) #define is_direct_le_key(version, key) \ (le_key_k_type(version, key) == TYPE_DIRECT) #define is_indirect_le_key(version, key) \ (le_key_k_type(version, key) == TYPE_INDIRECT) #define is_statdata_le_key(version, key) \ (le_key_k_type(version, key) == TYPE_STAT_DATA) /* Item header has version. */ #define is_direntry_le_ih(ih) \ is_direntry_le_key(ih_version(ih), &((ih)->ih_key)) #define is_direct_le_ih(ih) \ is_direct_le_key(ih_version(ih), &((ih)->ih_key)) #define is_indirect_le_ih(ih) \ is_indirect_le_key(ih_version(ih), &((ih)->ih_key)) #define is_statdata_le_ih(ih) \ is_statdata_le_key(ih_version(ih), &((ih)->ih_key)) static inline void set_cpu_key_k_offset(struct cpu_key *key, off_t offset) { (key->version == KEY_FORMAT_3_5) ? (key->on_disk_key.u.k_offset_v1.k_offset = offset) : (key->on_disk_key.u.k_offset_v2.k_offset = offset); } static inline void set_cpu_key_k_type(struct cpu_key *key, int type) { (key->version == KEY_FORMAT_3_5) ? (key->on_disk_key.u.k_offset_v1.k_uniqueness = type2uniqueness(type)): (key->on_disk_key.u.k_offset_v2.k_type = type); } #define is_direntry_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRENTRY) #define is_direct_cpu_key(key) (cpu_key_k_type (key) == TYPE_DIRECT) #define is_indirect_cpu_key(key) (cpu_key_k_type (key) == TYPE_INDIRECT) #define is_statdata_cpu_key(key) (cpu_key_k_type (key) == TYPE_STAT_DATA) /* Maximal length of item */ #define MAX_ITEM_LEN(block_size) (block_size - BLKH_SIZE - IH_SIZE) #define MIN_ITEM_LEN 1 /* Object identifier for root dir */ #define REISERFS_ROOT_OBJECTID 2 #define REISERFS_ROOT_PARENT_OBJECTID 1 /* key is pointer to cpu key, result is cpu */ static inline off_t cpu_key_k_offset(const struct cpu_key *key) { return ((key->version == KEY_FORMAT_3_5) ? key->on_disk_key.u.k_offset_v1.k_offset : key->on_disk_key.u.k_offset_v2.k_offset); } static inline off_t cpu_key_k_type(const struct cpu_key *key) { return ((key->version == KEY_FORMAT_3_5) ? uniqueness2type(key->on_disk_key.u.k_offset_v1.k_uniqueness) : key->on_disk_key.u.k_offset_v2.k_type); } /* * Header of a disk block. More precisely, header of a formatted leaf * or internal node, and not the header of an unformatted node. */ struct block_head { uint16_t blk_level; /* Level of a block in the tree. */ uint16_t blk_nr_item; /* Number of keys/items in a block. */ uint16_t blk_free_space; /* Block free space in bytes. */ uint16_t blk_reserved; /* Dump this in v4/planA */ struct key blk_right_delim_key; /* Kept only for compatibility */ }; #define BLKH_SIZE (sizeof(struct block_head)) #define blkh_level(p_blkh) (le16toh((p_blkh)->blk_level)) #define blkh_nr_item(p_blkh) (le16toh((p_blkh)->blk_nr_item)) #define blkh_free_space(p_blkh) (le16toh((p_blkh)->blk_free_space)) #define FREE_LEVEL 0 /* When node gets removed from the tree its blk_level is set to FREE_LEVEL. It is then used to see whether the node is still in the tree */ /* Values for blk_level field of the struct block_head */ #define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level.*/ /* * Given the buffer head of a formatted node, resolve to the block head * of that node. */ #define B_BLK_HEAD(p_s_bp) ((struct block_head *)((p_s_bp)->b_data)) #define B_NR_ITEMS(p_s_bp) (blkh_nr_item(B_BLK_HEAD(p_s_bp))) #define B_LEVEL(p_s_bp) (blkh_level(B_BLK_HEAD(p_s_bp))) #define B_FREE_SPACE(p_s_bp) (blkh_free_space(B_BLK_HEAD(p_s_bp))) /* ------------------------------------------------------------------- * Stat data * -------------------------------------------------------------------*/ /* * Old stat data is 32 bytes long. We are going to distinguish new one * by different size. */ struct stat_data_v1 { uint16_t sd_mode; /* File type, permissions */ uint16_t sd_nlink; /* Number of hard links */ uint16_t sd_uid; /* Owner */ uint16_t sd_gid; /* Group */ uint32_t sd_size; /* File size */ uint32_t sd_atime; /* Time of last access */ uint32_t sd_mtime; /* Time file was last modified */ uint32_t sd_ctime; /* Time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ union { uint32_t sd_rdev; uint32_t sd_blocks; /* Number of blocks file uses */ } __packed u; uint32_t sd_first_direct_byte; /* First byte of file which is stored in a direct item: except that if it equals 1 it is a symlink and if it equals ~(uint32_t)0 there is no direct item. The existence of this field really grates on me. Let's replace it with a macro based on sd_size and our tail suppression policy. Someday. -Hans */ } __packed; #define SD_V1_SIZE (sizeof(struct stat_data_v1)) #define stat_data_v1(ih) (ih_version (ih) == KEY_FORMAT_3_5) #define sd_v1_mode(sdp) (le16toh((sdp)->sd_mode)) #define set_sd_v1_mode(sdp, v) ((sdp)->sd_mode = htole16(v)) #define sd_v1_nlink(sdp) (le16toh((sdp)->sd_nlink)) #define set_sd_v1_nlink(sdp, v) ((sdp)->sd_nlink = htole16(v)) #define sd_v1_uid(sdp) (le16toh((sdp)->sd_uid)) #define set_sd_v1_uid(sdp, v) ((sdp)->sd_uid = htole16(v)) #define sd_v1_gid(sdp) (le16toh((sdp)->sd_gid)) #define set_sd_v1_gid(sdp, v) ((sdp)->sd_gid = htole16(v)) #define sd_v1_size(sdp) (le32toh((sdp)->sd_size)) #define set_sd_v1_size(sdp, v) ((sdp)->sd_size = htole32(v)) #define sd_v1_atime(sdp) (le32toh((sdp)->sd_atime)) #define set_sd_v1_atime(sdp, v) ((sdp)->sd_atime = htole32(v)) #define sd_v1_mtime(sdp) (le32toh((sdp)->sd_mtime)) #define set_sd_v1_mtime(sdp, v) ((sdp)->sd_mtime = htole32(v)) #define sd_v1_ctime(sdp) (le32toh((sdp)->sd_ctime)) #define set_sd_v1_ctime(sdp, v) ((sdp)->sd_ctime = htole32(v)) #define sd_v1_rdev(sdp) (le32toh((sdp)->u.sd_rdev)) #define set_sd_v1_rdev(sdp, v) ((sdp)->u.sd_rdev = htole32(v)) #define sd_v1_blocks(sdp) (le32toh((sdp)->u.sd_blocks)) #define set_sd_v1_blocks(sdp, v) ((sdp)->u.sd_blocks = htole32(v)) #define sd_v1_first_direct_byte(sdp) \ (le32toh((sdp)->sd_first_direct_byte)) #define set_sd_v1_first_direct_byte(sdp, v) \ ((sdp)->sd_first_direct_byte = htole32(v)) /* * We want common flags to have the same values as in ext2, * so chattr(1) will work without problems */ -#include +#include #define REISERFS_IMMUTABLE_FL EXT2_IMMUTABLE_FL #define REISERFS_APPEND_FL EXT2_APPEND_FL #define REISERFS_SYNC_FL EXT2_SYNC_FL #define REISERFS_NOATIME_FL EXT2_NOATIME_FL #define REISERFS_NODUMP_FL EXT2_NODUMP_FL #define REISERFS_SECRM_FL EXT2_SECRM_FL #define REISERFS_UNRM_FL EXT2_UNRM_FL #define REISERFS_COMPR_FL EXT2_COMPR_FL #define REISERFS_NOTAIL_FL EXT2_NOTAIL_FL /* * Stat Data on disk (reiserfs version of UFS disk inode minus the * address blocks) */ struct stat_data { uint16_t sd_mode; /* File type, permissions */ uint16_t sd_attrs; /* Persistent inode flags */ uint32_t sd_nlink; /* Number of hard links */ uint64_t sd_size; /* File size */ uint32_t sd_uid; /* Owner */ uint32_t sd_gid; /* Group */ uint32_t sd_atime; /* Time of last access */ uint32_t sd_mtime; /* Time file was last modified */ uint32_t sd_ctime; /* Time inode (stat data) was last changed (except changes to sd_atime and sd_mtime) */ uint32_t sd_blocks; union { uint32_t sd_rdev; uint32_t sd_generation; //uint32_t sd_first_direct_byte; /* * First byte of file which is stored in a * direct item: except that if it equals 1 * it is a symlink and if it equals * ~(uint32_t)0 there is no direct item. The * existence of this field really grates * on me. Let's replace it with a macro * based on sd_size and our tail * suppression policy? */ } __packed u; } __packed; /* This is 44 bytes long */ #define SD_SIZE (sizeof(struct stat_data)) #define SD_V2_SIZE SD_SIZE #define stat_data_v2(ih) (ih_version (ih) == KEY_FORMAT_3_6) #define sd_v2_mode(sdp) (le16toh((sdp)->sd_mode)) #define set_sd_v2_mode(sdp, v) ((sdp)->sd_mode = htole16(v)) /* sd_reserved */ /* set_sd_reserved */ #define sd_v2_nlink(sdp) (le32toh((sdp)->sd_nlink)) #define set_sd_v2_nlink(sdp, v) ((sdp)->sd_nlink = htole32(v)) #define sd_v2_size(sdp) (le64toh((sdp)->sd_size)) #define set_sd_v2_size(sdp, v) ((sdp)->sd_size = cpu_to_le64(v)) #define sd_v2_uid(sdp) (le32toh((sdp)->sd_uid)) #define set_sd_v2_uid(sdp, v) ((sdp)->sd_uid = htole32(v)) #define sd_v2_gid(sdp) (le32toh((sdp)->sd_gid)) #define set_sd_v2_gid(sdp, v) ((sdp)->sd_gid = htole32(v)) #define sd_v2_atime(sdp) (le32toh((sdp)->sd_atime)) #define set_sd_v2_atime(sdp, v) ((sdp)->sd_atime = htole32(v)) #define sd_v2_mtime(sdp) (le32toh((sdp)->sd_mtime)) #define set_sd_v2_mtime(sdp, v) ((sdp)->sd_mtime = htole32(v)) #define sd_v2_ctime(sdp) (le32toh((sdp)->sd_ctime)) #define set_sd_v2_ctime(sdp, v) ((sdp)->sd_ctime = htole32(v)) #define sd_v2_blocks(sdp) (le32toh((sdp)->sd_blocks)) #define set_sd_v2_blocks(sdp, v) ((sdp)->sd_blocks = htole32(v)) #define sd_v2_rdev(sdp) (le32toh((sdp)->u.sd_rdev)) #define set_sd_v2_rdev(sdp, v) ((sdp)->u.sd_rdev = htole32(v)) #define sd_v2_generation(sdp) (le32toh((sdp)->u.sd_generation)) #define set_sd_v2_generation(sdp, v) ((sdp)->u.sd_generation = htole32(v)) #define sd_v2_attrs(sdp) (le16toh((sdp)->sd_attrs)) #define set_sd_v2_attrs(sdp, v) ((sdp)->sd_attrs = htole16(v)) /* ------------------------------------------------------------------- * Directory structure * -------------------------------------------------------------------*/ #define SD_OFFSET 0 #define SD_UNIQUENESS 0 #define DOT_OFFSET 1 #define DOT_DOT_OFFSET 2 #define DIRENTRY_UNIQUENESS 500 #define FIRST_ITEM_OFFSET 1 struct reiserfs_de_head { uint32_t deh_offset; /* Third component of the directory entry key */ uint32_t deh_dir_id; /* Objectid of the parent directory of the object, that is referenced by directory entry */ uint32_t deh_objectid; /* Objectid of the object, that is referenced by directory entry */ uint16_t deh_location; /* Offset of name in the whole item */ uint16_t deh_state; /* Whether 1) entry contains stat data (for future), and 2) whether entry is hidden (unlinked) */ } __packed; #define DEH_SIZE sizeof(struct reiserfs_de_head) #define deh_offset(p_deh) (le32toh((p_deh)->deh_offset)) #define deh_dir_id(p_deh) (le32toh((p_deh)->deh_dir_id)) #define deh_objectid(p_deh) (le32toh((p_deh)->deh_objectid)) #define deh_location(p_deh) (le16toh((p_deh)->deh_location)) #define deh_state(p_deh) (le16toh((p_deh)->deh_state)) #define put_deh_offset(p_deh, v) ((p_deh)->deh_offset = htole32((v))) #define put_deh_dir_id(p_deh, v) ((p_deh)->deh_dir_id = htole32((v))) #define put_deh_objectid(p_deh, v) ((p_deh)->deh_objectid = htole32((v))) #define put_deh_location(p_deh, v) ((p_deh)->deh_location = htole16((v))) #define put_deh_state(p_deh, v) ((p_deh)->deh_state = htole16((v))) /* Empty directory contains two entries "." and ".." and their headers */ #define EMPTY_DIR_SIZE \ (DEH_SIZE * 2 + ROUND_UP(strlen(".")) + ROUND_UP(strlen(".."))) /* Old format directories have this size when empty */ #define EMPTY_DIR_SIZE_V1 (DEH_SIZE * 2 + 3) #define DEH_Statdata 0 /* Not used now */ #define DEH_Visible 2 /* 64 bit systems (and the S/390) need to be aligned explicitly -jdm */ #if BITS_PER_LONG == 64 || defined(__sparc64__) #define ADDR_UNALIGNED_BITS (3) #endif #ifdef ADDR_UNALIGNED_BITS #define aligned_address(addr) \ ((void *)((long)(addr) & ~((1UL << ADDR_UNALIGNED_BITS) - 1))) #define unaligned_offset(addr) \ (((int)((long)(addr) & ((1 << ADDR_UNALIGNED_BITS) - 1))) << 3) #define set_bit_unaligned(nr, addr) \ set_bit((nr) + unaligned_offset(addr), aligned_address(addr)) #define clear_bit_unaligned(nr, addr) \ clear_bit((nr) + unaligned_offset(addr), aligned_address(addr)) #define test_bit_unaligned(nr, addr) \ test_bit((nr) + unaligned_offset(addr), aligned_address(addr)) #else /* !defined ADDR_UNALIGNED_BITS */ #define set_bit_unaligned(nr, addr) set_bit(nr, addr) #define clear_bit_unaligned(nr, addr) clear_bit(nr, addr) #define test_bit_unaligned(nr, addr) test_bit(nr, addr) #endif /* defined ADDR_UNALIGNED_BITS */ #define mark_de_with_sd(deh) \ set_bit_unaligned(DEH_Statdata, &((deh)->deh_state)) #define mark_de_without_sd(deh) \ clear_bit_unaligned(DEH_Statdata, &((deh)->deh_state)) #define mark_de_visible(deh) \ set_bit_unaligned (DEH_Visible, &((deh)->deh_state)) #define mark_de_hidden(deh) \ clear_bit_unaligned (DEH_Visible, &((deh)->deh_state)) #define de_with_sd(deh) \ test_bit_unaligned(DEH_Statdata, &((deh)->deh_state)) #define de_visible(deh) \ test_bit_unaligned(DEH_Visible, &((deh)->deh_state)) #define de_hidden(deh) \ !test_bit_unaligned(DEH_Visible, &((deh)->deh_state)) /* Two entries per block (at least) */ #define REISERFS_MAX_NAME(block_size) 255 /* * This structure is used for operations on directory entries. It is not * a disk structure. When reiserfs_find_entry or search_by_entry_key * find directory entry, they return filled reiserfs_dir_entry structure */ struct reiserfs_dir_entry { struct buf *de_bp; int de_item_num; struct item_head *de_ih; int de_entry_num; struct reiserfs_de_head *de_deh; int de_entrylen; int de_namelen; char *de_name; char *de_gen_number_bit_string; uint32_t de_dir_id; uint32_t de_objectid; struct cpu_key de_entry_key; }; /* Pointer to file name, stored in entry */ #define B_I_DEH_ENTRY_FILE_NAME(bp, ih, deh) \ (B_I_PITEM(bp, ih) + deh_location(deh)) /* Length of name */ #define I_DEH_N_ENTRY_FILE_NAME_LENGTH(ih, deh, entry_num) \ (I_DEH_N_ENTRY_LENGTH(ih, deh, entry_num) - \ (de_with_sd(deh) ? SD_SIZE : 0)) /* Hash value occupies bits from 7 up to 30 */ #define GET_HASH_VALUE(offset) ((offset) & 0x7fffff80LL) /* Generation number occupies 7 bits starting from 0 up to 6 */ #define GET_GENERATION_NUMBER(offset) ((offset) & 0x7fLL) #define MAX_GENERATION_NUMBER 127 /* Get item body */ #define B_I_PITEM(bp, ih) ((bp)->b_data + ih_location(ih)) #define B_I_DEH(bp, ih) ((struct reiserfs_de_head *)(B_I_PITEM(bp, ih))) /* * Length of the directory entry in directory item. This define * calculates length of i-th directory entry using directory entry * locations from dir entry head. When it calculates length of 0-th * directory entry, it uses length of whole item in place of entry * location of the non-existent following entry in the calculation. See * picture above. */ static inline int entry_length (const struct buf *bp, const struct item_head *ih, int pos_in_item) { struct reiserfs_de_head *deh; deh = B_I_DEH(bp, ih) + pos_in_item; if (pos_in_item) return (deh_location(deh - 1) - deh_location(deh)); return (ih_item_len(ih) - deh_location(deh)); } /* * Number of entries in the directory item, depends on ENTRY_COUNT * being at the start of directory dynamic data. */ #define I_ENTRY_COUNT(ih) (ih_entry_count((ih))) /* ------------------------------------------------------------------- * Disk child * -------------------------------------------------------------------*/ /* * Disk child pointer: The pointer from an internal node of the tree * to a node that is on disk. */ struct disk_child { uint32_t dc_block_number; /* Disk child's block number. */ uint16_t dc_size; /* Disk child's used space. */ uint16_t dc_reserved; }; #define DC_SIZE (sizeof(struct disk_child)) #define dc_block_number(dc_p) (le32toh((dc_p)->dc_block_number)) #define dc_size(dc_p) (le16toh((dc_p)->dc_size)) #define put_dc_block_number(dc_p, val) \ do { (dc_p)->dc_block_number = htole32(val); } while (0) #define put_dc_size(dc_p, val) \ do { (dc_p)->dc_size = htole16(val); } while (0) /* Get disk child by buffer header and position in the tree node. */ #define B_N_CHILD(p_s_bp, n_pos) \ ((struct disk_child *)((p_s_bp)->b_data + BLKH_SIZE + \ B_NR_ITEMS(p_s_bp) * KEY_SIZE + \ DC_SIZE * (n_pos))) /* Get disk child number by buffer header and position in the tree node. */ #define B_N_CHILD_NUM(p_s_bp, n_pos) \ (dc_block_number(B_N_CHILD(p_s_bp, n_pos))) #define PUT_B_N_CHILD_NUM(p_s_bp, n_pos, val) \ (put_dc_block_number(B_N_CHILD(p_s_bp, n_pos), val)) /* ------------------------------------------------------------------- * Path structures and defines * -------------------------------------------------------------------*/ struct path_element { struct buf *pe_buffer; /* Pointer to the buffer at the path in the tree. */ int pe_position; /* Position in the tree node which is placed in the buffer above. */ }; #define MAX_HEIGHT 5 /* Maximal height of a tree. Don't change this without changing JOURNAL_PER_BALANCE_CNT */ #define EXTENDED_MAX_HEIGHT 7 /* Must be equals MAX_HEIGHT + FIRST_PATH_ELEMENT_OFFSET */ #define FIRST_PATH_ELEMENT_OFFSET 2 /* Must be equal to at least 2. */ #define ILLEGAL_PATH_ELEMENT_OFFSET 1 /* Must be equal to FIRST_PATH_ELEMENT_OFFSET - 1 */ #define MAX_FEB_SIZE 6 /* This MUST be MAX_HEIGHT + 1. See about FEB below */ struct path { /* Length of the array below. */ int path_length; /* Array of the path element */ struct path_element path_elements[EXTENDED_MAX_HEIGHT]; int pos_in_item; }; #define pos_in_item(path) ((path)->pos_in_item) #define INITIALIZE_PATH(var) \ struct path var = { ILLEGAL_PATH_ELEMENT_OFFSET, } /* Get path element by path and path position. */ #define PATH_OFFSET_PELEMENT(p_s_path, n_offset) \ ((p_s_path)->path_elements + (n_offset)) /* Get buffer header at the path by path and path position. */ #define PATH_OFFSET_PBUFFER(p_s_path, n_offset) \ (PATH_OFFSET_PELEMENT(p_s_path, n_offset)->pe_buffer) /* Get position in the element at the path by path and path position. */ #define PATH_OFFSET_POSITION(p_s_path, n_offset) \ (PATH_OFFSET_PELEMENT(p_s_path, n_offset)->pe_position) #define PATH_PLAST_BUFFER(p_s_path) \ (PATH_OFFSET_PBUFFER((p_s_path), (p_s_path)->path_length)) #define PATH_LAST_POSITION(p_s_path) \ (PATH_OFFSET_POSITION((p_s_path), (p_s_path)->path_length)) #define PATH_PITEM_HEAD(p_s_path) \ B_N_PITEM_HEAD(PATH_PLAST_BUFFER(p_s_path), PATH_LAST_POSITION(p_s_path)) #define get_last_bp(path) PATH_PLAST_BUFFER(path) #define get_ih(path) PATH_PITEM_HEAD(path) /* ------------------------------------------------------------------- * Misc. * -------------------------------------------------------------------*/ /* Size of pointer to the unformatted node. */ #define UNFM_P_SIZE (sizeof(unp_t)) #define UNFM_P_SHIFT 2 /* In in-core inode key is stored on le form */ #define INODE_PKEY(ip) ((struct key *)(REISERFS_I(ip)->i_key)) #define MAX_UL_INT 0xffffffff #define MAX_INT 0x7ffffff #define MAX_US_INT 0xffff /* The purpose is to detect overflow of an unsigned short */ #define REISERFS_LINK_MAX (MAX_US_INT - 1000) #define fs_generation(sbi) (REISERFS_SB(sbi)->s_generation_counter) #define get_generation(sbi) (fs_generation(sbi)) #define __fs_changed(gen, sbi) (gen != get_generation (sbi)) /*#define fs_changed(gen, sbi) ({ cond_resched(); \ __fs_changed(gen, sbi); })*/ #define fs_changed(gen, sbi) (__fs_changed(gen, sbi)) /* ------------------------------------------------------------------- * Fixate node * -------------------------------------------------------------------*/ /* * To make any changes in the tree we always first find node, that * contains item to be changed/deleted or place to insert a new item. * We call this node S. To do balancing we need to decide what we will * shift to left/right neighbor, or to a new node, where new item will * be etc. To make this analysis simpler we build virtual node. Virtual * node is an array of items, that will replace items of node S. (For * instance if we are going to delete an item, virtual node does not * contain it). Virtual node keeps information about item sizes and * types, mergeability of first and last items, sizes of all entries in * directory item. We use this array of items when calculating what we * can shift to neighbors and how many nodes we have to have if we do * not any shiftings, if we shift to left/right neighbor or to both. */ struct virtual_item { int vi_index; /* Index in the array of item operations */ unsigned short vi_type; /* Left/right mergeability */ unsigned short vi_item_len; /* Length of item that it will have after balancing */ struct item_head *vi_ih; const char *vi_item; /* Body of item (old or new) */ const void *vi_new_data; /* 0 always but paste mode */ void *vi_uarea; /* Item specific area */ }; struct virtual_node { char *vn_free_ptr; /* This is a pointer to the free space in the buffer */ unsigned short vn_nr_item; /* Number of items in virtual node */ short vn_size; /* Size of node , that node would have if it has unlimited size and no balancing is performed */ short vn_mode; /* Mode of balancing (paste, insert, delete, cut) */ short vn_affected_item_num; short vn_pos_in_item; struct item_head *vn_ins_ih; /* Item header of inserted item, 0 for other modes */ const void *vn_data; struct virtual_item *vn_vi; /* Array of items (including a new one, excluding item to be deleted) */ }; /* Used by directory items when creating virtual nodes */ struct direntry_uarea { int flags; uint16_t entry_count; uint16_t entry_sizes[1]; } __packed; /* ------------------------------------------------------------------- * Tree balance * -------------------------------------------------------------------*/ struct reiserfs_iget_args { uint32_t objectid; uint32_t dirid; }; struct item_operations { int (*bytes_number)(struct item_head * ih, int block_size); void (*decrement_key)(struct cpu_key *); int (*is_left_mergeable)(struct key * ih, unsigned long bsize); void (*print_item)(struct item_head *, char * item); void (*check_item)(struct item_head *, char * item); int (*create_vi)(struct virtual_node * vn, struct virtual_item * vi, int is_affected, int insert_size); int (*check_left)(struct virtual_item * vi, int free, int start_skip, int end_skip); int (*check_right)(struct virtual_item * vi, int free); int (*part_size)(struct virtual_item * vi, int from, int to); int (*unit_num)(struct virtual_item * vi); void (*print_vi)(struct virtual_item * vi); }; extern struct item_operations *item_ops[TYPE_ANY + 1]; #define op_bytes_number(ih, bsize) \ item_ops[le_ih_k_type(ih)]->bytes_number(ih, bsize) #define COMP_KEYS comp_keys #define COMP_SHORT_KEYS comp_short_keys /* Get the item header */ #define B_N_PITEM_HEAD(bp, item_num) \ ((struct item_head *)((bp)->b_data + BLKH_SIZE) + (item_num)) /* Get key */ #define B_N_PDELIM_KEY(bp, item_num) \ ((struct key *)((bp)->b_data + BLKH_SIZE) + (item_num)) /* ------------------------------------------------------------------- * Function declarations * -------------------------------------------------------------------*/ /* reiserfs_stree.c */ int B_IS_IN_TREE(const struct buf *p_s_bp); extern void copy_item_head(struct item_head * p_v_to, const struct item_head * p_v_from); extern int comp_keys(const struct key *le_key, const struct cpu_key *cpu_key); extern int comp_short_keys(const struct key *le_key, const struct cpu_key *cpu_key); extern int comp_le_keys(const struct key *, const struct key *); static inline int le_key_version(const struct key *key) { int type; type = offset_v2_k_type(&(key->u.k_offset_v2)); if (type != TYPE_DIRECT && type != TYPE_INDIRECT && type != TYPE_DIRENTRY) return (KEY_FORMAT_3_5); return (KEY_FORMAT_3_6); } static inline void copy_key(struct key *to, const struct key *from) { memcpy(to, from, KEY_SIZE); } const struct key *get_lkey(const struct path *p_s_chk_path, const struct reiserfs_sb_info *p_s_sbi); const struct key *get_rkey(const struct path *p_s_chk_path, const struct reiserfs_sb_info *p_s_sbi); inline int bin_search(const void * p_v_key, const void * p_v_base, int p_n_num, int p_n_width, int * p_n_pos); void pathrelse(struct path *p_s_search_path); int reiserfs_check_path(struct path *p); int search_by_key(struct reiserfs_sb_info *p_s_sbi, const struct cpu_key *p_s_key, struct path *p_s_search_path, int n_stop_level); #define search_item(sbi, key, path) \ search_by_key(sbi, key, path, DISK_LEAF_NODE_LEVEL) int search_for_position_by_key(struct reiserfs_sb_info *p_s_sbi, const struct cpu_key *p_s_cpu_key, struct path *p_s_search_path); void decrement_counters_in_path(struct path *p_s_search_path); /* reiserfs_inode.c */ vop_read_t reiserfs_read; vop_inactive_t reiserfs_inactive; vop_reclaim_t reiserfs_reclaim; int reiserfs_get_block(struct reiserfs_node *ip, long block, off_t offset, struct uio *uio); void make_cpu_key(struct cpu_key *cpu_key, struct reiserfs_node *ip, off_t offset, int type, int key_length); void reiserfs_read_locked_inode(struct reiserfs_node *ip, struct reiserfs_iget_args *args); int reiserfs_iget(struct mount *mp, const struct cpu_key *key, struct vnode **vpp, struct thread *td); void sd_attrs_to_i_attrs(uint16_t sd_attrs, struct reiserfs_node *ip); void i_attrs_to_sd_attrs(struct reiserfs_node *ip, uint16_t *sd_attrs); /* reiserfs_namei.c */ vop_readdir_t reiserfs_readdir; vop_cachedlookup_t reiserfs_lookup; void set_de_name_and_namelen(struct reiserfs_dir_entry * de); int search_by_entry_key(struct reiserfs_sb_info *sbi, const struct cpu_key *key, struct path *path, struct reiserfs_dir_entry *de); /* reiserfs_prints.c */ char *reiserfs_hashname(int code); void reiserfs_dump_buffer(caddr_t buf, off_t len); #if defined(REISERFS_DEBUG) #define reiserfs_log(lvl, fmt, ...) \ log(lvl, "ReiserFS/%s: " fmt, __func__, ## __VA_ARGS__) #elif defined (REISERFS_DEBUG_CONS) #define reiserfs_log(lvl, fmt, ...) \ printf("%s:%d: " fmt, __func__, __LINE__, ## __VA_ARGS__) #else #define reiserfs_log(lvl, fmt, ...) #endif #define reiserfs_log_0(lvl, fmt, ...) \ printf("%s:%d: " fmt, __func__, __LINE__, ## __VA_ARGS__) /* reiserfs_hashes.c */ uint32_t keyed_hash(const signed char *msg, int len); uint32_t yura_hash(const signed char *msg, int len); uint32_t r5_hash(const signed char *msg, int len); #define reiserfs_test_le_bit test_bit #endif /* !defined _GNU_REISERFS_REISERFS_FS_H */ diff --git a/sys/modules/ext2fs/Makefile b/sys/modules/ext2fs/Makefile index 2cd0b0709d8d..1ce8ab87aa28 100644 --- a/sys/modules/ext2fs/Makefile +++ b/sys/modules/ext2fs/Makefile @@ -1,10 +1,10 @@ # $FreeBSD$ -.PATH: ${.CURDIR}/../../gnu/ext2fs +.PATH: ${.CURDIR}/../../gnu/fs/ext2fs KMOD= ext2fs SRCS= opt_ddb.h opt_quota.h opt_suiddir.h vnode_if.h \ ext2_alloc.c ext2_balloc.c ext2_bmap.c ext2_inode.c \ ext2_inode_cnv.c ext2_linux_balloc.c ext2_linux_ialloc.c \ ext2_lookup.c ext2_subr.c ext2_vfsops.c ext2_vnops.c .include