Merge "Merge remote-tracking branch 'quic/tmp-d8ff506' into LA.BR.1.3.3 HEAD"

This commit is contained in:
Linux Build Service Account 2015-09-25 12:52:45 -07:00 committed by Gerrit - the friendly Code Review server
commit 8a02c8bfaf
169 changed files with 14026 additions and 2556 deletions

View File

@ -0,0 +1,16 @@
What: /sys/kernel/wakeup_reasons/last_resume_reason
Date: February 2014
Contact: Ruchi Kandoi <kandoiruchi@google.com>
Description:
The /sys/kernel/wakeup_reasons/last_resume_reason is
used to report wakeup reasons after system exited suspend.
What: /sys/kernel/wakeup_reasons/last_suspend_time
Date: March 2015
Contact: jinqian <jinqian@google.com>
Description:
The /sys/kernel/wakeup_reasons/last_suspend_time is
used to report time spent in last suspend cycle. It contains
two numbers (in seconds) separated by space. First number is
the time spent in suspend and resume processes. Second number
is the time spent in sleep state.

View File

@ -10,7 +10,7 @@ Construction Parameters
<version> <dev> <hash_dev>
<data_block_size> <hash_block_size>
<num_data_blocks> <hash_start_block>
<algorithm> <digest> <salt>
<algorithm> <digest> <salt> <mode>
<version>
This is the type of the on-disk hash format.
@ -62,6 +62,16 @@ Construction Parameters
<salt>
The hexadecimal encoding of the salt value.
<mode>
Optional. The mode of operation.
0 is the normal mode of operation where a corrupted block will result in an
I/O error.
1 is logging mode where corrupted blocks are logged and a uevent is sent to
notify user space.
Theory of operation
===================

View File

@ -28,6 +28,7 @@ Optional properties:
- cap-mmc-highspeed: MMC high-speed timing is supported
- cap-power-off-card: powering off the card is safe
- cap-sdio-irq: enable SDIO IRQ signalling on this interface
- full-pwr-cycle: full power cycle of the card is supported
*NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
polarity properties, we have to fix the meaning of the "normal" and "inverted"

View File

@ -445,3 +445,6 @@ object doesn't exist. It's remote/distributed ones that might care...
[mandatory]
FS_REVAL_DOT is gone; if you used to have it, add ->d_weak_revalidate()
in your dentry operations instead.
--
[mandatory]
vfs_readdir() is gone; switch to iterate_dir() instead

View File

@ -491,6 +491,10 @@ To clear the bits for the file mapped pages associated with the process
> echo 3 > /proc/PID/clear_refs
Any other value written to /proc/PID/clear_refs will have no effect.
To reset the peak resident set size ("high water mark") to the process's
current value:
> echo 5 > /proc/PID/clear_refs
The file /proc/PID/reclaim is used to reclaim pages in this process.
To reclaim file-backed pages,
> echo file > /proc/PID/reclaim
@ -525,50 +529,50 @@ files are there, and which are missing.
Table 1-5: Kernel info in /proc
..............................................................................
File Content
apm Advanced power management info
File Content
apm Advanced power management info
buddyinfo Kernel memory allocator information (see text) (2.5)
bus Directory containing bus specific information
cmdline Kernel command line
cpuinfo Info about the CPU
devices Available devices (block and character)
dma Used DMS channels
filesystems Supported filesystems
bus Directory containing bus specific information
cmdline Kernel command line
cpuinfo Info about the CPU
devices Available devices (block and character)
dma Used DMS channels
filesystems Supported filesystems
driver Various drivers grouped here, currently rtc (2.4)
execdomains Execdomains, related to security (2.4)
fb Frame Buffer devices (2.4)
fs File system parameters, currently nfs/exports (2.4)
ide Directory containing info about the IDE subsystem
interrupts Interrupt usage
ide Directory containing info about the IDE subsystem
interrupts Interrupt usage
iomem Memory map (2.4)
ioports I/O port usage
ioports I/O port usage
irq Masks for irq to cpu affinity (2.4)(smp?)
isapnp ISA PnP (Plug&Play) Info (2.4)
kcore Kernel core image (can be ELF or A.OUT(deprecated in 2.4))
kmsg Kernel messages
ksyms Kernel symbol table
loadavg Load average of last 1, 5 & 15 minutes
locks Kernel locks
meminfo Memory info
misc Miscellaneous
modules List of loaded modules
mounts Mounted filesystems
net Networking info (see text)
kcore Kernel core image (can be ELF or A.OUT(deprecated in 2.4))
kmsg Kernel messages
ksyms Kernel symbol table
loadavg Load average of last 1, 5 & 15 minutes
locks Kernel locks
meminfo Memory info
misc Miscellaneous
modules List of loaded modules
mounts Mounted filesystems
net Networking info (see text)
pagetypeinfo Additional page allocator information (see text) (2.5)
partitions Table of partitions known to the system
partitions Table of partitions known to the system
pci Deprecated info of PCI bus (new way -> /proc/bus/pci/,
decoupled by lspci (2.4)
rtc Real time clock
scsi SCSI info (see text)
slabinfo Slab pool info
rtc Real time clock
scsi SCSI info (see text)
slabinfo Slab pool info
softirqs softirq usage
stat Overall statistics
swaps Swap space utilization
sys See chapter 2
stat Overall statistics
swaps Swap space utilization
sys See chapter 2
sysvipc Info of SysVIPC Resources (msg, sem, shm) (2.4)
tty Info of tty drivers
uptime System uptime
version Kernel version
uptime System uptime
version Kernel version
video bttv info of video resources (2.4)
vmallocinfo Show vmalloced areas
..............................................................................
@ -576,28 +580,28 @@ Table 1-5: Kernel info in /proc
You can, for example, check which interrupts are currently in use and what
they are used for by looking in the file /proc/interrupts:
> cat /proc/interrupts
CPU0
0: 8728810 XT-PIC timer
1: 895 XT-PIC keyboard
2: 0 XT-PIC cascade
3: 531695 XT-PIC aha152x
4: 2014133 XT-PIC serial
5: 44401 XT-PIC pcnet_cs
8: 2 XT-PIC rtc
11: 8 XT-PIC i82365
12: 182918 XT-PIC PS/2 Mouse
13: 1 XT-PIC fpu
14: 1232265 XT-PIC ide0
15: 7 XT-PIC ide1
NMI: 0
> cat /proc/interrupts
CPU0
0: 8728810 XT-PIC timer
1: 895 XT-PIC keyboard
2: 0 XT-PIC cascade
3: 531695 XT-PIC aha152x
4: 2014133 XT-PIC serial
5: 44401 XT-PIC pcnet_cs
8: 2 XT-PIC rtc
11: 8 XT-PIC i82365
12: 182918 XT-PIC PS/2 Mouse
13: 1 XT-PIC fpu
14: 1232265 XT-PIC ide0
15: 7 XT-PIC ide1
NMI: 0
In 2.4.* a couple of lines where added to this file LOC & ERR (this time is the
output of a SMP machine):
> cat /proc/interrupts
> cat /proc/interrupts
CPU0 CPU1
CPU0 CPU1
0: 1243498 1214548 IO-APIC-edge timer
1: 8949 8958 IO-APIC-edge keyboard
2: 0 0 XT-PIC cascade
@ -610,8 +614,8 @@ output of a SMP machine):
15: 2183 2415 IO-APIC-edge ide1
17: 30564 30414 IO-APIC-level eth0
18: 177 164 IO-APIC-level bttv
NMI: 2457961 2457959
LOC: 2457882 2457881
NMI: 2457961 2457959
LOC: 2457882 2457881
ERR: 2155
NMI is incremented in this case because every timer interrupt generates a NMI
@ -658,7 +662,7 @@ IRQ to only one CPU, or to exclude a CPU of handling IRQs. The contents of the
irq subdir is one subdir for each IRQ, and two files; default_smp_affinity and
prof_cpu_mask.
For example
For example
> ls /proc/irq/
0 10 12 14 16 18 2 4 6 8 prof_cpu_mask
1 11 13 15 17 19 3 5 7 9 default_smp_affinity
@ -721,14 +725,14 @@ Node 0, zone Normal 1 0 0 1 101 8 ...
Node 0, zone HighMem 2 0 0 1 1 0 ...
External fragmentation is a problem under some workloads, and buddyinfo is a
useful tool for helping diagnose these problems. Buddyinfo will give you a
useful tool for helping diagnose these problems. Buddyinfo will give you a
clue as to how big an area you can safely allocate, or why a previous
allocation failed.
Each column represents the number of pages of a certain order which are
available. In this case, there are 0 chunks of 2^0*PAGE_SIZE available in
ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE
available in ZONE_NORMAL, etc...
Each column represents the number of pages of a certain order which are
available. In this case, there are 0 chunks of 2^0*PAGE_SIZE available in
ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE
available in ZONE_NORMAL, etc...
More information relevant to external fragmentation can be found in
pagetypeinfo.
@ -974,11 +978,11 @@ directories contains the files shown in table 1-6.
Table 1-6: IDE controller info in /proc/ide/ide?
..............................................................................
File Content
channel IDE channel (0 or 1)
config Configuration (only for PCI/IDE bridge)
mate Mate name
model Type/Chipset of IDE controller
File Content
channel IDE channel (0 or 1)
config Configuration (only for PCI/IDE bridge)
mate Mate name
model Type/Chipset of IDE controller
..............................................................................
Each device connected to a controller has a separate subdirectory in the
@ -988,41 +992,41 @@ directories.
Table 1-7: IDE device information
..............................................................................
File Content
cache The cache
capacity Capacity of the medium (in 512Byte blocks)
driver driver and version
geometry physical and logical geometry
identify device identify block
media media type
model device identifier
settings device setup
smart_thresholds IDE disk management thresholds
smart_values IDE disk management values
File Content
cache The cache
capacity Capacity of the medium (in 512Byte blocks)
driver driver and version
geometry physical and logical geometry
identify device identify block
media media type
model device identifier
settings device setup
smart_thresholds IDE disk management thresholds
smart_values IDE disk management values
..............................................................................
The most interesting file is settings. This file contains a nice overview of
the drive parameters:
# cat /proc/ide/ide0/hda/settings
name value min max mode
---- ----- --- --- ----
bios_cyl 526 0 65535 rw
bios_head 255 0 255 rw
bios_sect 63 0 63 rw
breada_readahead 4 0 127 rw
bswap 0 0 1 r
file_readahead 72 0 2097151 rw
io_32bit 0 0 3 rw
keepsettings 0 0 1 rw
max_kb_per_request 122 1 127 rw
multcount 0 0 8 rw
nice1 1 0 1 rw
nowerr 0 0 1 rw
pio_mode write-only 0 255 w
slow 0 0 1 rw
unmaskirq 0 0 1 rw
using_dma 0 0 1 rw
# cat /proc/ide/ide0/hda/settings
name value min max mode
---- ----- --- --- ----
bios_cyl 526 0 65535 rw
bios_head 255 0 255 rw
bios_sect 63 0 63 rw
breada_readahead 4 0 127 rw
bswap 0 0 1 r
file_readahead 72 0 2097151 rw
io_32bit 0 0 3 rw
keepsettings 0 0 1 rw
max_kb_per_request 122 1 127 rw
multcount 0 0 8 rw
nice1 1 0 1 rw
nowerr 0 0 1 rw
pio_mode write-only 0 255 w
slow 0 0 1 rw
unmaskirq 0 0 1 rw
using_dma 0 0 1 rw
1.4 Networking info in /proc/net
@ -1035,65 +1039,65 @@ support this. Table 1-9 lists the files and their meaning.
Table 1-8: IPv6 info in /proc/net
..............................................................................
File Content
udp6 UDP sockets (IPv6)
tcp6 TCP sockets (IPv6)
raw6 Raw device statistics (IPv6)
igmp6 IP multicast addresses, which this host joined (IPv6)
if_inet6 List of IPv6 interface addresses
ipv6_route Kernel routing table for IPv6
rt6_stats Global IPv6 routing tables statistics
sockstat6 Socket statistics (IPv6)
snmp6 Snmp data (IPv6)
File Content
udp6 UDP sockets (IPv6)
tcp6 TCP sockets (IPv6)
raw6 Raw device statistics (IPv6)
igmp6 IP multicast addresses, which this host joined (IPv6)
if_inet6 List of IPv6 interface addresses
ipv6_route Kernel routing table for IPv6
rt6_stats Global IPv6 routing tables statistics
sockstat6 Socket statistics (IPv6)
snmp6 Snmp data (IPv6)
..............................................................................
Table 1-9: Network info in /proc/net
..............................................................................
File Content
arp Kernel ARP table
dev network devices with statistics
File Content
arp Kernel ARP table
dev network devices with statistics
dev_mcast the Layer2 multicast groups a device is listening too
(interface index, label, number of references, number of bound
addresses).
dev_stat network device status
ip_fwchains Firewall chain linkage
ip_fwnames Firewall chain names
ip_masq Directory containing the masquerading tables
ip_masquerade Major masquerading table
netstat Network statistics
raw raw device statistics
route Kernel routing table
rpc Directory containing rpc info
rt_cache Routing cache
snmp SNMP data
sockstat Socket statistics
tcp TCP sockets
udp UDP sockets
unix UNIX domain sockets
wireless Wireless interface data (Wavelan etc)
igmp IP multicast addresses, which this host joined
psched Global packet scheduler parameters.
netlink List of PF_NETLINK sockets
ip_mr_vifs List of multicast virtual interfaces
ip_mr_cache List of multicast routing cache
addresses).
dev_stat network device status
ip_fwchains Firewall chain linkage
ip_fwnames Firewall chain names
ip_masq Directory containing the masquerading tables
ip_masquerade Major masquerading table
netstat Network statistics
raw raw device statistics
route Kernel routing table
rpc Directory containing rpc info
rt_cache Routing cache
snmp SNMP data
sockstat Socket statistics
tcp TCP sockets
udp UDP sockets
unix UNIX domain sockets
wireless Wireless interface data (Wavelan etc)
igmp IP multicast addresses, which this host joined
psched Global packet scheduler parameters.
netlink List of PF_NETLINK sockets
ip_mr_vifs List of multicast virtual interfaces
ip_mr_cache List of multicast routing cache
..............................................................................
You can use this information to see which network devices are available in
your system and how much traffic was routed over those devices:
> cat /proc/net/dev
Inter-|Receive |[...
face |bytes packets errs drop fifo frame compressed multicast|[...
lo: 908188 5596 0 0 0 0 0 0 [...
ppp0:15475140 20721 410 0 0 410 0 0 [...
eth0: 614530 7085 0 0 0 0 0 1 [...
...] Transmit
...] bytes packets errs drop fifo colls carrier compressed
...] 908188 5596 0 0 0 0 0 0
...] 1375103 17405 0 0 0 0 0 0
...] 1703981 5535 0 0 0 3 0 0
> cat /proc/net/dev
Inter-|Receive |[...
face |bytes packets errs drop fifo frame compressed multicast|[...
lo: 908188 5596 0 0 0 0 0 0 [...
ppp0:15475140 20721 410 0 0 410 0 0 [...
eth0: 614530 7085 0 0 0 0 0 1 [...
...] Transmit
...] bytes packets errs drop fifo colls carrier compressed
...] 908188 5596 0 0 0 0 0 0
...] 1375103 17405 0 0 0 0 0 0
...] 1703981 5535 0 0 0 3 0 0
In addition, each Channel Bond interface has its own directory. For
example, the bond0 device will have a directory called /proc/net/bond0/.
@ -1108,14 +1112,14 @@ If you have a SCSI host adapter in your system, you'll find a subdirectory
named after the driver for this adapter in /proc/scsi. You'll also see a list
of all recognized SCSI devices in /proc/scsi:
>cat /proc/scsi/scsi
Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
Vendor: IBM Model: DGHS09U Rev: 03E0
Type: Direct-Access ANSI SCSI revision: 03
Host: scsi0 Channel: 00 Id: 06 Lun: 00
Vendor: PIONEER Model: CD-ROM DR-U06S Rev: 1.04
Type: CD-ROM ANSI SCSI revision: 02
>cat /proc/scsi/scsi
Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
Vendor: IBM Model: DGHS09U Rev: 03E0
Type: Direct-Access ANSI SCSI revision: 03
Host: scsi0 Channel: 00 Id: 06 Lun: 00
Vendor: PIONEER Model: CD-ROM DR-U06S Rev: 1.04
Type: CD-ROM ANSI SCSI revision: 02
The directory named after the driver has one file for each adapter found in
@ -1124,44 +1128,44 @@ the used IRQ and the IO address range. The amount of information shown is
dependent on the adapter you use. The example shows the output for an Adaptec
AHA-2940 SCSI adapter:
> cat /proc/scsi/aic7xxx/0
Adaptec AIC7xxx driver version: 5.1.19/3.2.4
Compile Options:
TCQ Enabled By Default : Disabled
AIC7XXX_PROC_STATS : Disabled
AIC7XXX_RESET_DELAY : 5
Adapter Configuration:
SCSI Adapter: Adaptec AHA-294X Ultra SCSI host adapter
Ultra Wide Controller
PCI MMAPed I/O Base: 0xeb001000
Adapter SEEPROM Config: SEEPROM found and used.
Adaptec SCSI BIOS: Enabled
IRQ: 10
SCBs: Active 0, Max Active 2,
Allocated 15, HW 16, Page 255
Interrupts: 160328
BIOS Control Word: 0x18b6
Adapter Control Word: 0x005b
Extended Translation: Enabled
Disconnect Enable Flags: 0xffff
Ultra Enable Flags: 0x0001
Tag Queue Enable Flags: 0x0000
Ordered Queue Tag Flags: 0x0000
Default Tag Queue Depth: 8
Tagged Queue By Device array for aic7xxx host instance 0:
{255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}
Actual queue depth per device for aic7xxx host instance 0:
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
Statistics:
(scsi0:0:0:0)
Device using Wide/Sync transfers at 40.0 MByte/sec, offset 8
Transinfo settings: current(12/8/1/0), goal(12/8/1/0), user(12/15/1/0)
Total transfers 160151 (74577 reads and 85574 writes)
(scsi0:0:6:0)
Device using Narrow/Sync transfers at 5.0 MByte/sec, offset 15
Transinfo settings: current(50/15/0/0), goal(50/15/0/0), user(50/15/0/0)
Total transfers 0 (0 reads and 0 writes)
> cat /proc/scsi/aic7xxx/0
Adaptec AIC7xxx driver version: 5.1.19/3.2.4
Compile Options:
TCQ Enabled By Default : Disabled
AIC7XXX_PROC_STATS : Disabled
AIC7XXX_RESET_DELAY : 5
Adapter Configuration:
SCSI Adapter: Adaptec AHA-294X Ultra SCSI host adapter
Ultra Wide Controller
PCI MMAPed I/O Base: 0xeb001000
Adapter SEEPROM Config: SEEPROM found and used.
Adaptec SCSI BIOS: Enabled
IRQ: 10
SCBs: Active 0, Max Active 2,
Allocated 15, HW 16, Page 255
Interrupts: 160328
BIOS Control Word: 0x18b6
Adapter Control Word: 0x005b
Extended Translation: Enabled
Disconnect Enable Flags: 0xffff
Ultra Enable Flags: 0x0001
Tag Queue Enable Flags: 0x0000
Ordered Queue Tag Flags: 0x0000
Default Tag Queue Depth: 8
Tagged Queue By Device array for aic7xxx host instance 0:
{255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255}
Actual queue depth per device for aic7xxx host instance 0:
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
Statistics:
(scsi0:0:0:0)
Device using Wide/Sync transfers at 40.0 MByte/sec, offset 8
Transinfo settings: current(12/8/1/0), goal(12/8/1/0), user(12/15/1/0)
Total transfers 160151 (74577 reads and 85574 writes)
(scsi0:0:6:0)
Device using Narrow/Sync transfers at 5.0 MByte/sec, offset 15
Transinfo settings: current(50/15/0/0), goal(50/15/0/0), user(50/15/0/0)
Total transfers 0 (0 reads and 0 writes)
1.6 Parallel port info in /proc/parport
@ -1176,15 +1180,15 @@ These directories contain the four files shown in Table 1-10.
Table 1-10: Files in /proc/parport
..............................................................................
File Content
autoprobe Any IEEE-1284 device ID information that has been acquired.
File Content
autoprobe Any IEEE-1284 device ID information that has been acquired.
devices list of the device drivers using that port. A + will appear by the
name of the device currently using the port (it might not appear
against any).
hardware Parallel port's base address, IRQ line and DMA channel.
against any).
hardware Parallel port's base address, IRQ line and DMA channel.
irq IRQ that parport is using for that port. This is in a separate
file to allow you to alter it by writing a new value in (IRQ
number or none).
number or none).
..............................................................................
1.7 TTY info in /proc/tty
@ -1197,27 +1201,27 @@ this directory, as shown in Table 1-11.
Table 1-11: Files in /proc/tty
..............................................................................
File Content
drivers list of drivers and their usage
ldiscs registered line disciplines
driver/serial usage statistic and status of single tty lines
File Content
drivers list of drivers and their usage
ldiscs registered line disciplines
driver/serial usage statistic and status of single tty lines
..............................................................................
To see which tty's are currently in use, you can simply look into the file
/proc/tty/drivers:
> cat /proc/tty/drivers
pty_slave /dev/pts 136 0-255 pty:slave
pty_master /dev/ptm 128 0-255 pty:master
pty_slave /dev/ttyp 3 0-255 pty:slave
pty_master /dev/pty 2 0-255 pty:master
serial /dev/cua 5 64-67 serial:callout
serial /dev/ttyS 4 64-67 serial
/dev/tty0 /dev/tty0 4 0 system:vtmaster
/dev/ptmx /dev/ptmx 5 2 system
/dev/console /dev/console 5 1 system:console
/dev/tty /dev/tty 5 0 system:/dev/tty
unknown /dev/tty 4 1-63 console
> cat /proc/tty/drivers
pty_slave /dev/pts 136 0-255 pty:slave
pty_master /dev/ptm 128 0-255 pty:master
pty_slave /dev/ttyp 3 0-255 pty:slave
pty_master /dev/pty 2 0-255 pty:master
serial /dev/cua 5 64-67 serial:callout
serial /dev/ttyS 4 64-67 serial
/dev/tty0 /dev/tty0 4 0 system:vtmaster
/dev/ptmx /dev/ptmx 5 2 system
/dev/console /dev/console 5 1 system:console
/dev/tty /dev/tty 5 0 system:/dev/tty
unknown /dev/tty 4 1-63 console
1.8 Miscellaneous kernel statistics in /proc/stat
@ -1292,7 +1296,7 @@ in Table 1-12, below.
Table 1-12: Files in /proc/fs/ext4/<devname>
..............................................................................
File Content
File Content
mb_groups details of multiblock allocator buddy cache of free blocks
..............................................................................

View File

@ -2,10 +2,10 @@ SQUASHFS 4.0 FILESYSTEM
=======================
Squashfs is a compressed read-only filesystem for Linux.
It uses zlib/lzo/xz compression to compress files, inodes and directories.
Inodes in the system are very small and all blocks are packed to minimise
data overhead. Block sizes greater than 4K are supported up to a maximum
of 1Mbytes (default block size 128K).
It uses zlib, lz4, lzo, or xz compression to compress files, inodes and
directories. Inodes in the system are very small and all blocks are packed to
minimise data overhead. Block sizes greater than 4K are supported up to a
maximum of 1Mbytes (default block size 128K).
Squashfs is intended for general read-only filesystem use, for archival
use (i.e. in cases where a .tar.gz file may be used), and in constrained

View File

@ -4,10 +4,10 @@
# CONFIG_OABI_COMPAT is not set
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_INTF_ALARM_DEV=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_ARMV7_COMPAT=y
CONFIG_ASHMEM=y
CONFIG_AUDIT=y
CONFIG_BLK_DEV_DM=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_CGROUPS=y
@ -50,6 +50,7 @@ CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
@ -84,10 +85,12 @@ CONFIG_NETFILTER_XT_MATCH_TIME=y
CONFIG_NETFILTER_XT_MATCH_U32=y
CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
CONFIG_NETFILTER_XT_TARGET_MARK=y
CONFIG_NETFILTER_XT_TARGET_NFLOG=y
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
CONFIG_NETFILTER_XT_TARGET_TPROXY=y
CONFIG_NETFILTER_XT_TARGET_TRACE=y
@ -109,6 +112,7 @@ CONFIG_NF_CONNTRACK_IRC=y
CONFIG_NF_CONNTRACK_NETBIOS_NS=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SANE=y
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_TFTP=y
CONFIG_NF_CT_NETLINK=y
CONFIG_NF_CT_PROTO_DCCP=y
@ -129,6 +133,11 @@ CONFIG_PREEMPT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_RTC_CLASS=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SND=y
CONFIG_SOUND=y
CONFIG_STAGING=y
CONFIG_SWITCH=y
CONFIG_SYNC=y

View File

@ -96,6 +96,7 @@ struct osf_dirent {
};
struct osf_dirent_callback {
struct dir_context ctx;
struct osf_dirent __user *dirent;
long __user *basep;
unsigned int count;
@ -146,17 +147,17 @@ SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd,
{
int error;
struct fd arg = fdget(fd);
struct osf_dirent_callback buf;
struct osf_dirent_callback buf = {
.ctx.actor = osf_filldir,
.dirent = dirent,
.basep = basep,
.count = count
};
if (!arg.file)
return -EBADF;
buf.dirent = dirent;
buf.basep = basep;
buf.count = count;
buf.error = 0;
error = vfs_readdir(arg.file, osf_filldir, &buf);
error = iterate_dir(arg.file, &buf.ctx);
if (error >= 0)
error = buf.error;
if (count != buf.count)

View File

@ -6,12 +6,15 @@ obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o
obj-$(CONFIG_CRYPTO_AES_ARM_BS) += aes-arm-bs.o
obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o
obj-$(CONFIG_CRYPTO_SHA1_ARM_NEON) += sha1-arm-neon.o
obj-$(CONFIG_CRYPTO_SHA256_ARM) += sha256-arm.o
obj-$(CONFIG_CRYPTO_SHA512_ARM_NEON) += sha512-arm-neon.o
aes-arm-y := aes-armv4.o aes_glue.o
aes-arm-bs-y := aesbs-core.o aesbs-glue.o
sha1-arm-y := sha1-armv4-large.o sha1_glue.o
sha1-arm-neon-y := sha1-armv7-neon.o sha1_neon_glue.o
sha256-arm-neon-$(CONFIG_KERNEL_MODE_NEON) := sha256_neon_glue.o
sha256-arm-y := sha256-core.o sha256_glue.o $(sha256-arm-neon-y)
sha512-arm-neon-y := sha512-armv7-neon.o sha512_neon_glue.o
quiet_cmd_perl = PERL $@
@ -20,4 +23,7 @@ quiet_cmd_perl = PERL $@
$(src)/aesbs-core.S_shipped: $(src)/bsaes-armv7.pl
$(call cmd,perl)
.PRECIOUS: $(obj)/aesbs-core.S
$(src)/sha256-core.S_shipped: $(src)/sha256-armv4.pl
$(call cmd,perl)
.PRECIOUS: $(obj)/aesbs-core.S $(obj)/sha256-core.S

View File

@ -0,0 +1,716 @@
#!/usr/bin/env perl
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
#
# Permission to use under GPL terms is granted.
# ====================================================================
# SHA256 block procedure for ARMv4. May 2007.
# Performance is ~2x better than gcc 3.4 generated code and in "abso-
# lute" terms is ~2250 cycles per 64-byte block or ~35 cycles per
# byte [on single-issue Xscale PXA250 core].
# July 2010.
#
# Rescheduling for dual-issue pipeline resulted in 22% improvement on
# Cortex A8 core and ~20 cycles per processed byte.
# February 2011.
#
# Profiler-assisted and platform-specific optimization resulted in 16%
# improvement on Cortex A8 core and ~15.4 cycles per processed byte.
# September 2013.
#
# Add NEON implementation. On Cortex A8 it was measured to process one
# byte in 12.5 cycles or 23% faster than integer-only code. Snapdragon
# S4 does it in 12.5 cycles too, but it's 50% faster than integer-only
# code (meaning that latter performs sub-optimally, nothing was done
# about it).
# May 2014.
#
# Add ARMv8 code path performing at 2.0 cpb on Apple A7.
while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {}
open STDOUT,">$output";
$ctx="r0"; $t0="r0";
$inp="r1"; $t4="r1";
$len="r2"; $t1="r2";
$T1="r3"; $t3="r3";
$A="r4";
$B="r5";
$C="r6";
$D="r7";
$E="r8";
$F="r9";
$G="r10";
$H="r11";
@V=($A,$B,$C,$D,$E,$F,$G,$H);
$t2="r12";
$Ktbl="r14";
@Sigma0=( 2,13,22);
@Sigma1=( 6,11,25);
@sigma0=( 7,18, 3);
@sigma1=(17,19,10);
sub BODY_00_15 {
my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_;
$code.=<<___ if ($i<16);
#if __ARM_ARCH__>=7
@ ldr $t1,[$inp],#4 @ $i
# if $i==15
str $inp,[sp,#17*4] @ make room for $t4
# endif
eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]`
add $a,$a,$t2 @ h+=Maj(a,b,c) from the past
eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e)
# ifndef __ARMEB__
rev $t1,$t1
# endif
#else
@ ldrb $t1,[$inp,#3] @ $i
add $a,$a,$t2 @ h+=Maj(a,b,c) from the past
ldrb $t2,[$inp,#2]
ldrb $t0,[$inp,#1]
orr $t1,$t1,$t2,lsl#8
ldrb $t2,[$inp],#4
orr $t1,$t1,$t0,lsl#16
# if $i==15
str $inp,[sp,#17*4] @ make room for $t4
# endif
eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]`
orr $t1,$t1,$t2,lsl#24
eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e)
#endif
___
$code.=<<___;
ldr $t2,[$Ktbl],#4 @ *K256++
add $h,$h,$t1 @ h+=X[i]
str $t1,[sp,#`$i%16`*4]
eor $t1,$f,$g
add $h,$h,$t0,ror#$Sigma1[0] @ h+=Sigma1(e)
and $t1,$t1,$e
add $h,$h,$t2 @ h+=K256[i]
eor $t1,$t1,$g @ Ch(e,f,g)
eor $t0,$a,$a,ror#`$Sigma0[1]-$Sigma0[0]`
add $h,$h,$t1 @ h+=Ch(e,f,g)
#if $i==31
and $t2,$t2,#0xff
cmp $t2,#0xf2 @ done?
#endif
#if $i<15
# if __ARM_ARCH__>=7
ldr $t1,[$inp],#4 @ prefetch
# else
ldrb $t1,[$inp,#3]
# endif
eor $t2,$a,$b @ a^b, b^c in next round
#else
ldr $t1,[sp,#`($i+2)%16`*4] @ from future BODY_16_xx
eor $t2,$a,$b @ a^b, b^c in next round
ldr $t4,[sp,#`($i+15)%16`*4] @ from future BODY_16_xx
#endif
eor $t0,$t0,$a,ror#`$Sigma0[2]-$Sigma0[0]` @ Sigma0(a)
and $t3,$t3,$t2 @ (b^c)&=(a^b)
add $d,$d,$h @ d+=h
eor $t3,$t3,$b @ Maj(a,b,c)
add $h,$h,$t0,ror#$Sigma0[0] @ h+=Sigma0(a)
@ add $h,$h,$t3 @ h+=Maj(a,b,c)
___
($t2,$t3)=($t3,$t2);
}
sub BODY_16_XX {
my ($i,$a,$b,$c,$d,$e,$f,$g,$h) = @_;
$code.=<<___;
@ ldr $t1,[sp,#`($i+1)%16`*4] @ $i
@ ldr $t4,[sp,#`($i+14)%16`*4]
mov $t0,$t1,ror#$sigma0[0]
add $a,$a,$t2 @ h+=Maj(a,b,c) from the past
mov $t2,$t4,ror#$sigma1[0]
eor $t0,$t0,$t1,ror#$sigma0[1]
eor $t2,$t2,$t4,ror#$sigma1[1]
eor $t0,$t0,$t1,lsr#$sigma0[2] @ sigma0(X[i+1])
ldr $t1,[sp,#`($i+0)%16`*4]
eor $t2,$t2,$t4,lsr#$sigma1[2] @ sigma1(X[i+14])
ldr $t4,[sp,#`($i+9)%16`*4]
add $t2,$t2,$t0
eor $t0,$e,$e,ror#`$Sigma1[1]-$Sigma1[0]` @ from BODY_00_15
add $t1,$t1,$t2
eor $t0,$t0,$e,ror#`$Sigma1[2]-$Sigma1[0]` @ Sigma1(e)
add $t1,$t1,$t4 @ X[i]
___
&BODY_00_15(@_);
}
$code=<<___;
#ifndef __KERNEL__
# include "arm_arch.h"
#else
# define __ARM_ARCH__ __LINUX_ARM_ARCH__
# define __ARM_MAX_ARCH__ 7
#endif
.text
#if __ARM_ARCH__<7
.code 32
#else
.syntax unified
# ifdef __thumb2__
# define adrl adr
.thumb
# else
.code 32
# endif
#endif
.type K256,%object
.align 5
K256:
.word 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5
.word 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5
.word 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3
.word 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174
.word 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc
.word 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da
.word 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7
.word 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967
.word 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13
.word 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85
.word 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3
.word 0xd192e819,0xd6990624,0xf40e3585,0x106aa070
.word 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5
.word 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3
.word 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208
.word 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
.size K256,.-K256
.word 0 @ terminator
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.LOPENSSL_armcap:
.word OPENSSL_armcap_P-sha256_block_data_order
#endif
.align 5
.global sha256_block_data_order
.type sha256_block_data_order,%function
sha256_block_data_order:
#if __ARM_ARCH__<7
sub r3,pc,#8 @ sha256_block_data_order
#else
adr r3,sha256_block_data_order
#endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
ldr r12,[r3,r12] @ OPENSSL_armcap_P
tst r12,#ARMV8_SHA256
bne .LARMv8
tst r12,#ARMV7_NEON
bne .LNEON
#endif
add $len,$inp,$len,lsl#6 @ len to point at the end of inp
stmdb sp!,{$ctx,$inp,$len,r4-r11,lr}
ldmia $ctx,{$A,$B,$C,$D,$E,$F,$G,$H}
sub $Ktbl,r3,#256+32 @ K256
sub sp,sp,#16*4 @ alloca(X[16])
.Loop:
# if __ARM_ARCH__>=7
ldr $t1,[$inp],#4
# else
ldrb $t1,[$inp,#3]
# endif
eor $t3,$B,$C @ magic
eor $t2,$t2,$t2
___
for($i=0;$i<16;$i++) { &BODY_00_15($i,@V); unshift(@V,pop(@V)); }
$code.=".Lrounds_16_xx:\n";
for (;$i<32;$i++) { &BODY_16_XX($i,@V); unshift(@V,pop(@V)); }
$code.=<<___;
#if __ARM_ARCH__>=7
ite eq @ Thumb2 thing, sanity check in ARM
#endif
ldreq $t3,[sp,#16*4] @ pull ctx
bne .Lrounds_16_xx
add $A,$A,$t2 @ h+=Maj(a,b,c) from the past
ldr $t0,[$t3,#0]
ldr $t1,[$t3,#4]
ldr $t2,[$t3,#8]
add $A,$A,$t0
ldr $t0,[$t3,#12]
add $B,$B,$t1
ldr $t1,[$t3,#16]
add $C,$C,$t2
ldr $t2,[$t3,#20]
add $D,$D,$t0
ldr $t0,[$t3,#24]
add $E,$E,$t1
ldr $t1,[$t3,#28]
add $F,$F,$t2
ldr $inp,[sp,#17*4] @ pull inp
ldr $t2,[sp,#18*4] @ pull inp+len
add $G,$G,$t0
add $H,$H,$t1
stmia $t3,{$A,$B,$C,$D,$E,$F,$G,$H}
cmp $inp,$t2
sub $Ktbl,$Ktbl,#256 @ rewind Ktbl
bne .Loop
add sp,sp,#`16+3`*4 @ destroy frame
#if __ARM_ARCH__>=5
ldmia sp!,{r4-r11,pc}
#else
ldmia sp!,{r4-r11,lr}
tst lr,#1
moveq pc,lr @ be binary compatible with V4, yet
bx lr @ interoperable with Thumb ISA:-)
#endif
.size sha256_block_data_order,.-sha256_block_data_order
___
######################################################################
# NEON stuff
#
{{{
my @X=map("q$_",(0..3));
my ($T0,$T1,$T2,$T3,$T4,$T5)=("q8","q9","q10","q11","d24","d25");
my $Xfer=$t4;
my $j=0;
sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; }
sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; }
sub AUTOLOAD() # thunk [simplified] x86-style perlasm
{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
my $arg = pop;
$arg = "#$arg" if ($arg*1 eq $arg);
$code .= "\t$opcode\t".join(',',@_,$arg)."\n";
}
sub Xupdate()
{ use integer;
my $body = shift;
my @insns = (&$body,&$body,&$body,&$body);
my ($a,$b,$c,$d,$e,$f,$g,$h);
&vext_8 ($T0,@X[0],@X[1],4); # X[1..4]
eval(shift(@insns));
eval(shift(@insns));
eval(shift(@insns));
&vext_8 ($T1,@X[2],@X[3],4); # X[9..12]
eval(shift(@insns));
eval(shift(@insns));
eval(shift(@insns));
&vshr_u32 ($T2,$T0,$sigma0[0]);
eval(shift(@insns));
eval(shift(@insns));
&vadd_i32 (@X[0],@X[0],$T1); # X[0..3] += X[9..12]
eval(shift(@insns));
eval(shift(@insns));
&vshr_u32 ($T1,$T0,$sigma0[2]);
eval(shift(@insns));
eval(shift(@insns));
&vsli_32 ($T2,$T0,32-$sigma0[0]);
eval(shift(@insns));
eval(shift(@insns));
&vshr_u32 ($T3,$T0,$sigma0[1]);
eval(shift(@insns));
eval(shift(@insns));
&veor ($T1,$T1,$T2);
eval(shift(@insns));
eval(shift(@insns));
&vsli_32 ($T3,$T0,32-$sigma0[1]);
eval(shift(@insns));
eval(shift(@insns));
&vshr_u32 ($T4,&Dhi(@X[3]),$sigma1[0]);
eval(shift(@insns));
eval(shift(@insns));
&veor ($T1,$T1,$T3); # sigma0(X[1..4])
eval(shift(@insns));
eval(shift(@insns));
&vsli_32 ($T4,&Dhi(@X[3]),32-$sigma1[0]);
eval(shift(@insns));
eval(shift(@insns));
&vshr_u32 ($T5,&Dhi(@X[3]),$sigma1[2]);
eval(shift(@insns));
eval(shift(@insns));
&vadd_i32 (@X[0],@X[0],$T1); # X[0..3] += sigma0(X[1..4])
eval(shift(@insns));
eval(shift(@insns));
&veor ($T5,$T5,$T4);
eval(shift(@insns));
eval(shift(@insns));
&vshr_u32 ($T4,&Dhi(@X[3]),$sigma1[1]);
eval(shift(@insns));
eval(shift(@insns));
&vsli_32 ($T4,&Dhi(@X[3]),32-$sigma1[1]);
eval(shift(@insns));
eval(shift(@insns));
&veor ($T5,$T5,$T4); # sigma1(X[14..15])
eval(shift(@insns));
eval(shift(@insns));
&vadd_i32 (&Dlo(@X[0]),&Dlo(@X[0]),$T5);# X[0..1] += sigma1(X[14..15])
eval(shift(@insns));
eval(shift(@insns));
&vshr_u32 ($T4,&Dlo(@X[0]),$sigma1[0]);
eval(shift(@insns));
eval(shift(@insns));
&vsli_32 ($T4,&Dlo(@X[0]),32-$sigma1[0]);
eval(shift(@insns));
eval(shift(@insns));
&vshr_u32 ($T5,&Dlo(@X[0]),$sigma1[2]);
eval(shift(@insns));
eval(shift(@insns));
&veor ($T5,$T5,$T4);
eval(shift(@insns));
eval(shift(@insns));
&vshr_u32 ($T4,&Dlo(@X[0]),$sigma1[1]);
eval(shift(@insns));
eval(shift(@insns));
&vld1_32 ("{$T0}","[$Ktbl,:128]!");
eval(shift(@insns));
eval(shift(@insns));
&vsli_32 ($T4,&Dlo(@X[0]),32-$sigma1[1]);
eval(shift(@insns));
eval(shift(@insns));
&veor ($T5,$T5,$T4); # sigma1(X[16..17])
eval(shift(@insns));
eval(shift(@insns));
&vadd_i32 (&Dhi(@X[0]),&Dhi(@X[0]),$T5);# X[2..3] += sigma1(X[16..17])
eval(shift(@insns));
eval(shift(@insns));
&vadd_i32 ($T0,$T0,@X[0]);
while($#insns>=2) { eval(shift(@insns)); }
&vst1_32 ("{$T0}","[$Xfer,:128]!");
eval(shift(@insns));
eval(shift(@insns));
push(@X,shift(@X)); # "rotate" X[]
}
sub Xpreload()
{ use integer;
my $body = shift;
my @insns = (&$body,&$body,&$body,&$body);
my ($a,$b,$c,$d,$e,$f,$g,$h);
eval(shift(@insns));
eval(shift(@insns));
eval(shift(@insns));
eval(shift(@insns));
&vld1_32 ("{$T0}","[$Ktbl,:128]!");
eval(shift(@insns));
eval(shift(@insns));
eval(shift(@insns));
eval(shift(@insns));
&vrev32_8 (@X[0],@X[0]);
eval(shift(@insns));
eval(shift(@insns));
eval(shift(@insns));
eval(shift(@insns));
&vadd_i32 ($T0,$T0,@X[0]);
foreach (@insns) { eval; } # remaining instructions
&vst1_32 ("{$T0}","[$Xfer,:128]!");
push(@X,shift(@X)); # "rotate" X[]
}
sub body_00_15 () {
(
'($a,$b,$c,$d,$e,$f,$g,$h)=@V;'.
'&add ($h,$h,$t1)', # h+=X[i]+K[i]
'&eor ($t1,$f,$g)',
'&eor ($t0,$e,$e,"ror#".($Sigma1[1]-$Sigma1[0]))',
'&add ($a,$a,$t2)', # h+=Maj(a,b,c) from the past
'&and ($t1,$t1,$e)',
'&eor ($t2,$t0,$e,"ror#".($Sigma1[2]-$Sigma1[0]))', # Sigma1(e)
'&eor ($t0,$a,$a,"ror#".($Sigma0[1]-$Sigma0[0]))',
'&eor ($t1,$t1,$g)', # Ch(e,f,g)
'&add ($h,$h,$t2,"ror#$Sigma1[0]")', # h+=Sigma1(e)
'&eor ($t2,$a,$b)', # a^b, b^c in next round
'&eor ($t0,$t0,$a,"ror#".($Sigma0[2]-$Sigma0[0]))', # Sigma0(a)
'&add ($h,$h,$t1)', # h+=Ch(e,f,g)
'&ldr ($t1,sprintf "[sp,#%d]",4*(($j+1)&15)) if (($j&15)!=15);'.
'&ldr ($t1,"[$Ktbl]") if ($j==15);'.
'&ldr ($t1,"[sp,#64]") if ($j==31)',
'&and ($t3,$t3,$t2)', # (b^c)&=(a^b)
'&add ($d,$d,$h)', # d+=h
'&add ($h,$h,$t0,"ror#$Sigma0[0]");'. # h+=Sigma0(a)
'&eor ($t3,$t3,$b)', # Maj(a,b,c)
'$j++; unshift(@V,pop(@V)); ($t2,$t3)=($t3,$t2);'
)
}
$code.=<<___;
#if __ARM_MAX_ARCH__>=7
.arch armv7-a
.fpu neon
.global sha256_block_data_order_neon
.type sha256_block_data_order_neon,%function
.align 4
sha256_block_data_order_neon:
.LNEON:
stmdb sp!,{r4-r12,lr}
sub $H,sp,#16*4+16
adrl $Ktbl,K256
bic $H,$H,#15 @ align for 128-bit stores
mov $t2,sp
mov sp,$H @ alloca
add $len,$inp,$len,lsl#6 @ len to point at the end of inp
vld1.8 {@X[0]},[$inp]!
vld1.8 {@X[1]},[$inp]!
vld1.8 {@X[2]},[$inp]!
vld1.8 {@X[3]},[$inp]!
vld1.32 {$T0},[$Ktbl,:128]!
vld1.32 {$T1},[$Ktbl,:128]!
vld1.32 {$T2},[$Ktbl,:128]!
vld1.32 {$T3},[$Ktbl,:128]!
vrev32.8 @X[0],@X[0] @ yes, even on
str $ctx,[sp,#64]
vrev32.8 @X[1],@X[1] @ big-endian
str $inp,[sp,#68]
mov $Xfer,sp
vrev32.8 @X[2],@X[2]
str $len,[sp,#72]
vrev32.8 @X[3],@X[3]
str $t2,[sp,#76] @ save original sp
vadd.i32 $T0,$T0,@X[0]
vadd.i32 $T1,$T1,@X[1]
vst1.32 {$T0},[$Xfer,:128]!
vadd.i32 $T2,$T2,@X[2]
vst1.32 {$T1},[$Xfer,:128]!
vadd.i32 $T3,$T3,@X[3]
vst1.32 {$T2},[$Xfer,:128]!
vst1.32 {$T3},[$Xfer,:128]!
ldmia $ctx,{$A-$H}
sub $Xfer,$Xfer,#64
ldr $t1,[sp,#0]
eor $t2,$t2,$t2
eor $t3,$B,$C
b .L_00_48
.align 4
.L_00_48:
___
&Xupdate(\&body_00_15);
&Xupdate(\&body_00_15);
&Xupdate(\&body_00_15);
&Xupdate(\&body_00_15);
$code.=<<___;
teq $t1,#0 @ check for K256 terminator
ldr $t1,[sp,#0]
sub $Xfer,$Xfer,#64
bne .L_00_48
ldr $inp,[sp,#68]
ldr $t0,[sp,#72]
sub $Ktbl,$Ktbl,#256 @ rewind $Ktbl
teq $inp,$t0
it eq
subeq $inp,$inp,#64 @ avoid SEGV
vld1.8 {@X[0]},[$inp]! @ load next input block
vld1.8 {@X[1]},[$inp]!
vld1.8 {@X[2]},[$inp]!
vld1.8 {@X[3]},[$inp]!
it ne
strne $inp,[sp,#68]
mov $Xfer,sp
___
&Xpreload(\&body_00_15);
&Xpreload(\&body_00_15);
&Xpreload(\&body_00_15);
&Xpreload(\&body_00_15);
$code.=<<___;
ldr $t0,[$t1,#0]
add $A,$A,$t2 @ h+=Maj(a,b,c) from the past
ldr $t2,[$t1,#4]
ldr $t3,[$t1,#8]
ldr $t4,[$t1,#12]
add $A,$A,$t0 @ accumulate
ldr $t0,[$t1,#16]
add $B,$B,$t2
ldr $t2,[$t1,#20]
add $C,$C,$t3
ldr $t3,[$t1,#24]
add $D,$D,$t4
ldr $t4,[$t1,#28]
add $E,$E,$t0
str $A,[$t1],#4
add $F,$F,$t2
str $B,[$t1],#4
add $G,$G,$t3
str $C,[$t1],#4
add $H,$H,$t4
str $D,[$t1],#4
stmia $t1,{$E-$H}
ittte ne
movne $Xfer,sp
ldrne $t1,[sp,#0]
eorne $t2,$t2,$t2
ldreq sp,[sp,#76] @ restore original sp
itt ne
eorne $t3,$B,$C
bne .L_00_48
ldmia sp!,{r4-r12,pc}
.size sha256_block_data_order_neon,.-sha256_block_data_order_neon
#endif
___
}}}
######################################################################
# ARMv8 stuff
#
{{{
my ($ABCD,$EFGH,$abcd)=map("q$_",(0..2));
my @MSG=map("q$_",(8..11));
my ($W0,$W1,$ABCD_SAVE,$EFGH_SAVE)=map("q$_",(12..15));
my $Ktbl="r3";
$code.=<<___;
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
# ifdef __thumb2__
# define INST(a,b,c,d) .byte c,d|0xc,a,b
# else
# define INST(a,b,c,d) .byte a,b,c,d
# endif
.type sha256_block_data_order_armv8,%function
.align 5
sha256_block_data_order_armv8:
.LARMv8:
vld1.32 {$ABCD,$EFGH},[$ctx]
# ifdef __thumb2__
adr $Ktbl,.LARMv8
sub $Ktbl,$Ktbl,#.LARMv8-K256
# else
adrl $Ktbl,K256
# endif
add $len,$inp,$len,lsl#6 @ len to point at the end of inp
.Loop_v8:
vld1.8 {@MSG[0]-@MSG[1]},[$inp]!
vld1.8 {@MSG[2]-@MSG[3]},[$inp]!
vld1.32 {$W0},[$Ktbl]!
vrev32.8 @MSG[0],@MSG[0]
vrev32.8 @MSG[1],@MSG[1]
vrev32.8 @MSG[2],@MSG[2]
vrev32.8 @MSG[3],@MSG[3]
vmov $ABCD_SAVE,$ABCD @ offload
vmov $EFGH_SAVE,$EFGH
teq $inp,$len
___
for($i=0;$i<12;$i++) {
$code.=<<___;
vld1.32 {$W1},[$Ktbl]!
vadd.i32 $W0,$W0,@MSG[0]
sha256su0 @MSG[0],@MSG[1]
vmov $abcd,$ABCD
sha256h $ABCD,$EFGH,$W0
sha256h2 $EFGH,$abcd,$W0
sha256su1 @MSG[0],@MSG[2],@MSG[3]
___
($W0,$W1)=($W1,$W0); push(@MSG,shift(@MSG));
}
$code.=<<___;
vld1.32 {$W1},[$Ktbl]!
vadd.i32 $W0,$W0,@MSG[0]
vmov $abcd,$ABCD
sha256h $ABCD,$EFGH,$W0
sha256h2 $EFGH,$abcd,$W0
vld1.32 {$W0},[$Ktbl]!
vadd.i32 $W1,$W1,@MSG[1]
vmov $abcd,$ABCD
sha256h $ABCD,$EFGH,$W1
sha256h2 $EFGH,$abcd,$W1
vld1.32 {$W1},[$Ktbl]
vadd.i32 $W0,$W0,@MSG[2]
sub $Ktbl,$Ktbl,#256-16 @ rewind
vmov $abcd,$ABCD
sha256h $ABCD,$EFGH,$W0
sha256h2 $EFGH,$abcd,$W0
vadd.i32 $W1,$W1,@MSG[3]
vmov $abcd,$ABCD
sha256h $ABCD,$EFGH,$W1
sha256h2 $EFGH,$abcd,$W1
vadd.i32 $ABCD,$ABCD,$ABCD_SAVE
vadd.i32 $EFGH,$EFGH,$EFGH_SAVE
it ne
bne .Loop_v8
vst1.32 {$ABCD,$EFGH},[$ctx]
ret @ bx lr
.size sha256_block_data_order_armv8,.-sha256_block_data_order_armv8
#endif
___
}}}
$code.=<<___;
.asciz "SHA256 block transform for ARMv4/NEON/ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
.align 2
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
.comm OPENSSL_armcap_P,4,4
#endif
___
open SELF,$0;
while(<SELF>) {
next if (/^#!/);
last if (!s/^#/@/ and !/^$/);
print;
}
close SELF;
{ my %opcode = (
"sha256h" => 0xf3000c40, "sha256h2" => 0xf3100c40,
"sha256su0" => 0xf3ba03c0, "sha256su1" => 0xf3200c40 );
sub unsha256 {
my ($mnemonic,$arg)=@_;
if ($arg =~ m/q([0-9]+)(?:,\s*q([0-9]+))?,\s*q([0-9]+)/o) {
my $word = $opcode{$mnemonic}|(($1&7)<<13)|(($1&8)<<19)
|(($2&7)<<17)|(($2&8)<<4)
|(($3&7)<<1) |(($3&8)<<2);
# since ARMv7 instructions are always encoded little-endian.
# correct solution is to use .inst directive, but older
# assemblers don't implement it:-(
sprintf "INST(0x%02x,0x%02x,0x%02x,0x%02x)\t@ %s %s",
$word&0xff,($word>>8)&0xff,
($word>>16)&0xff,($word>>24)&0xff,
$mnemonic,$arg;
}
}
}
foreach (split($/,$code)) {
s/\`([^\`]*)\`/eval $1/geo;
s/\b(sha256\w+)\s+(q.*)/unsha256($1,$2)/geo;
s/\bret\b/bx lr/go or
s/\bbx\s+lr\b/.word\t0xe12fff1e/go; # make it possible to compile with -march=armv4
print $_,"\n";
}
close STDOUT; # enforce flush

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,246 @@
/*
* Glue code for the SHA256 Secure Hash Algorithm assembly implementation
* using optimized ARM assembler and NEON instructions.
*
* Copyright © 2015 Google Inc.
*
* This file is based on sha256_ssse3_glue.c:
* Copyright (C) 2013 Intel Corporation
* Author: Tim Chen <tim.c.chen@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
*/
#include <crypto/internal/hash.h>
#include <linux/crypto.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/cryptohash.h>
#include <linux/types.h>
#include <linux/string.h>
#include <crypto/sha.h>
#include <asm/byteorder.h>
#include <asm/simd.h>
#include <asm/neon.h>
#include "sha256_glue.h"
asmlinkage void sha256_block_data_order(u32 *digest, const void *data,
unsigned int num_blks);
int sha256_init(struct shash_desc *desc)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
sctx->state[0] = SHA256_H0;
sctx->state[1] = SHA256_H1;
sctx->state[2] = SHA256_H2;
sctx->state[3] = SHA256_H3;
sctx->state[4] = SHA256_H4;
sctx->state[5] = SHA256_H5;
sctx->state[6] = SHA256_H6;
sctx->state[7] = SHA256_H7;
sctx->count = 0;
return 0;
}
int sha224_init(struct shash_desc *desc)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
sctx->state[0] = SHA224_H0;
sctx->state[1] = SHA224_H1;
sctx->state[2] = SHA224_H2;
sctx->state[3] = SHA224_H3;
sctx->state[4] = SHA224_H4;
sctx->state[5] = SHA224_H5;
sctx->state[6] = SHA224_H6;
sctx->state[7] = SHA224_H7;
sctx->count = 0;
return 0;
}
int __sha256_update(struct shash_desc *desc, const u8 *data, unsigned int len,
unsigned int partial)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
unsigned int done = 0;
sctx->count += len;
if (partial) {
done = SHA256_BLOCK_SIZE - partial;
memcpy(sctx->buf + partial, data, done);
sha256_block_data_order(sctx->state, sctx->buf, 1);
}
if (len - done >= SHA256_BLOCK_SIZE) {
const unsigned int rounds = (len - done) / SHA256_BLOCK_SIZE;
sha256_block_data_order(sctx->state, data + done, rounds);
done += rounds * SHA256_BLOCK_SIZE;
}
memcpy(sctx->buf, data + done, len - done);
return 0;
}
int sha256_update(struct shash_desc *desc, const u8 *data, unsigned int len)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
unsigned int partial = sctx->count % SHA256_BLOCK_SIZE;
/* Handle the fast case right here */
if (partial + len < SHA256_BLOCK_SIZE) {
sctx->count += len;
memcpy(sctx->buf + partial, data, len);
return 0;
}
return __sha256_update(desc, data, len, partial);
}
/* Add padding and return the message digest. */
static int sha256_final(struct shash_desc *desc, u8 *out)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
unsigned int i, index, padlen;
__be32 *dst = (__be32 *)out;
__be64 bits;
static const u8 padding[SHA256_BLOCK_SIZE] = { 0x80, };
/* save number of bits */
bits = cpu_to_be64(sctx->count << 3);
/* Pad out to 56 mod 64 and append length */
index = sctx->count % SHA256_BLOCK_SIZE;
padlen = (index < 56) ? (56 - index) : ((SHA256_BLOCK_SIZE+56)-index);
/* We need to fill a whole block for __sha256_update */
if (padlen <= 56) {
sctx->count += padlen;
memcpy(sctx->buf + index, padding, padlen);
} else {
__sha256_update(desc, padding, padlen, index);
}
__sha256_update(desc, (const u8 *)&bits, sizeof(bits), 56);
/* Store state in digest */
for (i = 0; i < 8; i++)
dst[i] = cpu_to_be32(sctx->state[i]);
/* Wipe context */
memset(sctx, 0, sizeof(*sctx));
return 0;
}
static int sha224_final(struct shash_desc *desc, u8 *out)
{
u8 D[SHA256_DIGEST_SIZE];
sha256_final(desc, D);
memcpy(out, D, SHA224_DIGEST_SIZE);
memset(D, 0, SHA256_DIGEST_SIZE);
return 0;
}
int sha256_export(struct shash_desc *desc, void *out)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
memcpy(out, sctx, sizeof(*sctx));
return 0;
}
int sha256_import(struct shash_desc *desc, const void *in)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
memcpy(sctx, in, sizeof(*sctx));
return 0;
}
static struct shash_alg algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_init,
.update = sha256_update,
.final = sha256_final,
.export = sha256_export,
.import = sha256_import,
.descsize = sizeof(struct sha256_state),
.statesize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-asm",
.cra_priority = 150,
.cra_flags = CRYPTO_ALG_TYPE_SHASH,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
}, {
.digestsize = SHA224_DIGEST_SIZE,
.init = sha224_init,
.update = sha256_update,
.final = sha224_final,
.export = sha256_export,
.import = sha256_import,
.descsize = sizeof(struct sha256_state),
.statesize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha224",
.cra_driver_name = "sha224-asm",
.cra_priority = 150,
.cra_flags = CRYPTO_ALG_TYPE_SHASH,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
} };
static int __init sha256_mod_init(void)
{
int res = crypto_register_shashes(algs, ARRAY_SIZE(algs));
if (res < 0)
return res;
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && cpu_has_neon()) {
res = crypto_register_shashes(sha256_neon_algs,
ARRAY_SIZE(sha256_neon_algs));
if (res < 0)
crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
}
return res;
}
static void __exit sha256_mod_fini(void)
{
crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && cpu_has_neon())
crypto_unregister_shashes(sha256_neon_algs,
ARRAY_SIZE(sha256_neon_algs));
}
module_init(sha256_mod_init);
module_exit(sha256_mod_fini);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm (ARM), including NEON");
MODULE_ALIAS("sha256");

View File

@ -0,0 +1,23 @@
#ifndef _CRYPTO_SHA256_GLUE_H
#define _CRYPTO_SHA256_GLUE_H
#include <linux/crypto.h>
#include <crypto/sha.h>
extern struct shash_alg sha256_neon_algs[2];
extern int sha256_init(struct shash_desc *desc);
extern int sha224_init(struct shash_desc *desc);
extern int __sha256_update(struct shash_desc *desc, const u8 *data,
unsigned int len, unsigned int partial);
extern int sha256_update(struct shash_desc *desc, const u8 *data,
unsigned int len);
extern int sha256_export(struct shash_desc *desc, void *out);
extern int sha256_import(struct shash_desc *desc, const void *in);
#endif /* _CRYPTO_SHA256_GLUE_H */

View File

@ -0,0 +1,172 @@
/*
* Glue code for the SHA256 Secure Hash Algorithm assembly implementation
* using NEON instructions.
*
* Copyright © 2015 Google Inc.
*
* This file is based on sha512_neon_glue.c:
* Copyright © 2014 Jussi Kivilinna <jussi.kivilinna@iki.fi>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
*/
#include <crypto/internal/hash.h>
#include <linux/cryptohash.h>
#include <linux/types.h>
#include <linux/string.h>
#include <crypto/sha.h>
#include <asm/byteorder.h>
#include <asm/simd.h>
#include <asm/neon.h>
#include "sha256_glue.h"
asmlinkage void sha256_block_data_order_neon(u32 *digest, const void *data,
unsigned int num_blks);
static int __sha256_neon_update(struct shash_desc *desc, const u8 *data,
unsigned int len, unsigned int partial)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
unsigned int done = 0;
sctx->count += len;
if (partial) {
done = SHA256_BLOCK_SIZE - partial;
memcpy(sctx->buf + partial, data, done);
sha256_block_data_order_neon(sctx->state, sctx->buf, 1);
}
if (len - done >= SHA256_BLOCK_SIZE) {
const unsigned int rounds = (len - done) / SHA256_BLOCK_SIZE;
sha256_block_data_order_neon(sctx->state, data + done, rounds);
done += rounds * SHA256_BLOCK_SIZE;
}
memcpy(sctx->buf, data + done, len - done);
return 0;
}
static int sha256_neon_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
unsigned int partial = sctx->count % SHA256_BLOCK_SIZE;
int res;
/* Handle the fast case right here */
if (partial + len < SHA256_BLOCK_SIZE) {
sctx->count += len;
memcpy(sctx->buf + partial, data, len);
return 0;
}
if (!may_use_simd()) {
res = __sha256_update(desc, data, len, partial);
} else {
kernel_neon_begin();
res = __sha256_neon_update(desc, data, len, partial);
kernel_neon_end();
}
return res;
}
/* Add padding and return the message digest. */
static int sha256_neon_final(struct shash_desc *desc, u8 *out)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
unsigned int i, index, padlen;
__be32 *dst = (__be32 *)out;
__be64 bits;
static const u8 padding[SHA256_BLOCK_SIZE] = { 0x80, };
/* save number of bits */
bits = cpu_to_be64(sctx->count << 3);
/* Pad out to 56 mod 64 and append length */
index = sctx->count % SHA256_BLOCK_SIZE;
padlen = (index < 56) ? (56 - index) : ((SHA256_BLOCK_SIZE+56)-index);
if (!may_use_simd()) {
sha256_update(desc, padding, padlen);
sha256_update(desc, (const u8 *)&bits, sizeof(bits));
} else {
kernel_neon_begin();
/* We need to fill a whole block for __sha256_neon_update() */
if (padlen <= 56) {
sctx->count += padlen;
memcpy(sctx->buf + index, padding, padlen);
} else {
__sha256_neon_update(desc, padding, padlen, index);
}
__sha256_neon_update(desc, (const u8 *)&bits,
sizeof(bits), 56);
kernel_neon_end();
}
/* Store state in digest */
for (i = 0; i < 8; i++)
dst[i] = cpu_to_be32(sctx->state[i]);
/* Wipe context */
memset(sctx, 0, sizeof(*sctx));
return 0;
}
static int sha224_neon_final(struct shash_desc *desc, u8 *out)
{
u8 D[SHA256_DIGEST_SIZE];
sha256_neon_final(desc, D);
memcpy(out, D, SHA224_DIGEST_SIZE);
memset(D, 0, SHA256_DIGEST_SIZE);
return 0;
}
struct shash_alg sha256_neon_algs[] = { {
.digestsize = SHA256_DIGEST_SIZE,
.init = sha256_init,
.update = sha256_neon_update,
.final = sha256_neon_final,
.export = sha256_export,
.import = sha256_import,
.descsize = sizeof(struct sha256_state),
.statesize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-neon",
.cra_priority = 250,
.cra_flags = CRYPTO_ALG_TYPE_SHASH,
.cra_blocksize = SHA256_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
}, {
.digestsize = SHA224_DIGEST_SIZE,
.init = sha224_init,
.update = sha256_neon_update,
.final = sha224_neon_final,
.export = sha256_export,
.import = sha256_import,
.descsize = sizeof(struct sha256_state),
.statesize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha224",
.cra_driver_name = "sha224-neon",
.cra_priority = 250,
.cra_flags = CRYPTO_ALG_TYPE_SHASH,
.cra_blocksize = SHA224_BLOCK_SIZE,
.cra_module = THIS_MODULE,
}
} };

View File

@ -60,6 +60,7 @@ struct hpux_dirent {
};
struct getdents_callback {
struct dir_context ctx;
struct hpux_dirent __user *current_dir;
struct hpux_dirent __user *previous;
int count;
@ -110,24 +111,23 @@ int hpux_getdents(unsigned int fd, struct hpux_dirent __user *dirent, unsigned i
{
struct fd arg;
struct hpux_dirent __user * lastdirent;
struct getdents_callback buf;
struct getdents_callback buf = {
.ctx.actor = filldir,
.current_dir = dirent,
.count = count
};
int error;
arg = fdget(fd);
if (!arg.file)
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
error = vfs_readdir(arg.file, filldir, &buf);
error = iterate_dir(arg.file, &buf.ctx);
if (error >= 0)
error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
if (put_user(arg.file->f_pos, &lastdirent->d_off))
if (put_user(buf.ctx.pos, &lastdirent->d_off))
error = -EFAULT;
else
error = count - buf.count;

View File

@ -6,13 +6,13 @@
#ifndef __FRAME_KERN_H_
#define __FRAME_KERN_H_
extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
struct k_sigaction *ka,
struct pt_regs *regs,
struct pt_regs *regs,
sigset_t *mask);
extern int setup_signal_stack_si(unsigned long stack_top, int sig,
extern int setup_signal_stack_si(unsigned long stack_top, int sig,
struct k_sigaction *ka,
struct pt_regs *regs, siginfo_t *info,
struct pt_regs *regs, struct siginfo *info,
sigset_t *mask);
#endif

View File

@ -19,7 +19,7 @@ EXPORT_SYMBOL(unblock_signals);
* OK, we're invoking a handler
*/
static void handle_signal(struct pt_regs *regs, unsigned long signr,
struct k_sigaction *ka, siginfo_t *info)
struct k_sigaction *ka, struct siginfo *info)
{
sigset_t *oldset = sigmask_to_save();
int singlestep = 0;
@ -71,7 +71,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
static int kern_do_signal(struct pt_regs *regs)
{
struct k_sigaction ka_copy;
siginfo_t info;
struct siginfo info;
int sig, handled_sig = 0;
while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {

View File

@ -25,7 +25,7 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
[SIGIO] = sigio_handler,
[SIGVTALRM] = timer_handler };
static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc)
static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
{
struct uml_pt_regs r;
int save_errno = errno;
@ -61,7 +61,7 @@ static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc)
static int signals_enabled;
static unsigned int signals_pending;
void sig_handler(int sig, siginfo_t *si, mcontext_t *mc)
void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
{
int enabled;
@ -120,7 +120,7 @@ void set_sigstack(void *sig_stack, int size)
panic("enabling signal stack failed, errno = %d\n", errno);
}
static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = {
static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
[SIGSEGV] = sig_handler,
[SIGBUS] = sig_handler,
[SIGILL] = sig_handler,
@ -162,7 +162,7 @@ static void hard_handler(int sig, siginfo_t *si, void *p)
while ((sig = ffs(pending)) != 0){
sig--;
pending &= ~(1 << sig);
(*handlers[sig])(sig, si, mc);
(*handlers[sig])(sig, (struct siginfo *)si, mc);
}
/*

View File

@ -409,7 +409,7 @@ void userspace(struct uml_pt_regs *regs)
if (WIFSTOPPED(status)) {
int sig = WSTOPSIG(status);
ptrace(PTRACE_GETSIGINFO, pid, 0, &si);
ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si);
switch (sig) {
case SIGSEGV:
@ -417,7 +417,7 @@ void userspace(struct uml_pt_regs *regs)
!ptrace_faultinfo) {
get_skas_faultinfo(pid,
&regs->faultinfo);
(*sig_info[SIGSEGV])(SIGSEGV, &si,
(*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,
regs);
}
else handle_segv(pid, regs);
@ -426,14 +426,14 @@ void userspace(struct uml_pt_regs *regs)
handle_trap(pid, regs, local_using_sysemu);
break;
case SIGTRAP:
relay_signal(SIGTRAP, &si, regs);
relay_signal(SIGTRAP, (struct siginfo *)&si, regs);
break;
case SIGVTALRM:
now = os_nsecs();
if (now < nsecs)
break;
block_signals();
(*sig_info[sig])(sig, &si, regs);
(*sig_info[sig])(sig, (struct siginfo *)&si, regs);
unblock_signals();
nsecs = timer.it_value.tv_sec *
UM_NSEC_PER_SEC +
@ -447,7 +447,7 @@ void userspace(struct uml_pt_regs *regs)
case SIGFPE:
case SIGWINCH:
block_signals();
(*sig_info[sig])(sig, &si, regs);
(*sig_info[sig])(sig, (struct siginfo *)&si, regs);
unblock_signals();
break;
default:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -660,6 +660,10 @@ static inline void cpu_relax(void)
rep_nop();
}
#ifndef cpu_read_relax
#define cpu_read_relax() cpu_relax()
#endif
/* Stop speculative execution and prefetching of modified code. */
static inline void sync_core(void)
{

View File

@ -0,0 +1,22 @@
/*
* x86/include/asm/relaxed.h
*
* (copied from arm/include/asm/relaxed.h)
*
* Copyright (c) 2014 NVIDIA Corporation. All rights reserved.
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _ASM_RELAXED_H_
#define _ASM_RELAXED_H_
#include <asm-generic/relaxed.h>
#endif /*_ASM_RELAXED_H_*/

View File

@ -508,7 +508,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
{
struct rt_sigframe __user *frame;
int err = 0;
struct task_struct *me = current;
frame = (struct rt_sigframe __user *)
round_down(stack_top - sizeof(struct rt_sigframe), 16);

View File

@ -556,6 +556,13 @@ config CRYPTO_SHA256
This code also includes SHA-224, a 224 bit hash with 112 bits
of security against collision attacks.
config CRYPTO_SHA256_ARM
tristate "SHA-224/256 digest algorithm (ARM-asm and NEON)"
select CRYPTO_HASH
help
SHA-256 secure hash standard (DFIPS 180-2) implemented
using optimized ARM assembler and NEON, when available.
config CRYPTO_SHA256_SPARC64
tristate "SHA224 and SHA256 digest algorithm (SPARC64)"
depends on SPARC64

View File

@ -3585,13 +3585,24 @@ static int binder_transactions_show(struct seq_file *m, void *unused)
static int binder_proc_show(struct seq_file *m, void *unused)
{
struct binder_proc *itr;
struct binder_proc *proc = m->private;
int do_lock = !binder_debug_no_lock;
bool valid_proc = false;
if (do_lock)
binder_lock(__func__);
seq_puts(m, "binder proc state:\n");
print_binder_proc(m, proc, 1);
hlist_for_each_entry(itr, &binder_procs, proc_node) {
if (itr == proc) {
valid_proc = true;
break;
}
}
if (valid_proc) {
seq_puts(m, "binder proc state:\n");
print_binder_proc(m, proc, 1);
}
if (do_lock)
binder_unlock(__func__);
return 0;

View File

@ -1,3 +1,4 @@
#if !defined(__i386__) && !defined(__amd64__)
/*
* Coherent per-device memory handling.
* Borrowed from i386
@ -218,3 +219,228 @@ int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
return 0;
}
EXPORT_SYMBOL(dma_mmap_from_coherent);
#else
/* CMA is a wretched hive of scum and villany --- and also doesn't
* compile on x86 */
/*
* Coherent per-device memory handling.
* Borrowed from i386
*/
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
struct dma_coherent_mem {
void *virt_base;
dma_addr_t device_base;
phys_addr_t pfn_base;
int size;
int flags;
unsigned long *bitmap;
};
int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dma_addr_t device_addr, size_t size, int flags)
{
void __iomem *mem_base = NULL;
int pages = size >> PAGE_SHIFT;
int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
goto out;
if (!size)
goto out;
if (dev->dma_mem)
goto out;
/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
mem_base = ioremap(bus_addr, size);
if (!mem_base)
goto out;
dev->dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
if (!dev->dma_mem)
goto out;
dev->dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!dev->dma_mem->bitmap)
goto free1_out;
dev->dma_mem->virt_base = mem_base;
dev->dma_mem->device_base = device_addr;
dev->dma_mem->pfn_base = PFN_DOWN(bus_addr);
dev->dma_mem->size = pages;
dev->dma_mem->flags = flags;
if (flags & DMA_MEMORY_MAP)
return DMA_MEMORY_MAP;
return DMA_MEMORY_IO;
free1_out:
kfree(dev->dma_mem);
out:
if (mem_base)
iounmap(mem_base);
return 0;
}
EXPORT_SYMBOL(dma_declare_coherent_memory);
void dma_release_declared_memory(struct device *dev)
{
struct dma_coherent_mem *mem = dev->dma_mem;
if (!mem)
return;
dev->dma_mem = NULL;
iounmap(mem->virt_base);
kfree(mem->bitmap);
kfree(mem);
}
EXPORT_SYMBOL(dma_release_declared_memory);
void *dma_mark_declared_memory_occupied(struct device *dev,
dma_addr_t device_addr, size_t size)
{
struct dma_coherent_mem *mem = dev->dma_mem;
int pos, err;
size += device_addr & ~PAGE_MASK;
if (!mem)
return ERR_PTR(-EINVAL);
pos = (device_addr - mem->device_base) >> PAGE_SHIFT;
err = bitmap_allocate_region(mem->bitmap, pos, get_order(size));
if (err != 0)
return ERR_PTR(err);
return mem->virt_base + (pos << PAGE_SHIFT);
}
EXPORT_SYMBOL(dma_mark_declared_memory_occupied);
/**
* dma_alloc_from_coherent() - try to allocate memory from the per-device coherent area
*
* @dev: device from which we allocate memory
* @size: size of requested memory area
* @dma_handle: This will be filled with the correct dma handle
* @ret: This pointer will be filled with the virtual address
* to allocated area.
*
* This function should be only called from per-arch dma_alloc_coherent()
* to support allocation from per-device coherent memory pools.
*
* Returns 0 if dma_alloc_coherent should continue with allocating from
* generic memory areas, or !0 if dma_alloc_coherent should return @ret.
*/
int dma_alloc_from_coherent(struct device *dev, ssize_t size,
dma_addr_t *dma_handle, void **ret)
{
struct dma_coherent_mem *mem;
int order = get_order(size);
int pageno;
if (!dev)
return 0;
mem = dev->dma_mem;
if (!mem)
return 0;
*ret = NULL;
if (unlikely(size > (mem->size << PAGE_SHIFT)))
goto err;
pageno = bitmap_find_free_region(mem->bitmap, mem->size, order);
if (unlikely(pageno < 0))
goto err;
/*
* Memory was found in the per-device area.
*/
*dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
*ret = mem->virt_base + (pageno << PAGE_SHIFT);
memset(*ret, 0, size);
return 1;
err:
/*
* In the case where the allocation can not be satisfied from the
* per-device area, try to fall back to generic memory if the
* constraints allow it.
*/
return mem->flags & DMA_MEMORY_EXCLUSIVE;
}
EXPORT_SYMBOL(dma_alloc_from_coherent);
/**
* dma_release_from_coherent() - try to free the memory allocated from per-device coherent memory pool
* @dev: device from which the memory was allocated
* @order: the order of pages allocated
* @vaddr: virtual address of allocated pages
*
* This checks whether the memory was allocated from the per-device
* coherent memory pool and if so, releases that memory.
*
* Returns 1 if we correctly released the memory, or 0 if
* dma_release_coherent() should proceed with releasing memory from
* generic pools.
*/
int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
{
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
if (mem && vaddr >= mem->virt_base && vaddr <
(mem->virt_base + (mem->size << PAGE_SHIFT))) {
int page = (vaddr - mem->virt_base) >> PAGE_SHIFT;
bitmap_release_region(mem->bitmap, page, order);
return 1;
}
return 0;
}
EXPORT_SYMBOL(dma_release_from_coherent);
/**
* dma_mmap_from_coherent() - try to mmap the memory allocated from
* per-device coherent memory pool to userspace
* @dev: device from which the memory was allocated
* @vma: vm_area for the userspace memory
* @vaddr: cpu address returned by dma_alloc_from_coherent
* @size: size of the memory buffer allocated by dma_alloc_from_coherent
* @ret: result from remap_pfn_range()
*
* This checks whether the memory was allocated from the per-device
* coherent memory pool and if so, maps that memory to the provided vma.
*
* Returns 1 if we correctly mapped the memory, or 0 if the caller should
* proceed with mapping memory from generic pools.
*/
int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
void *vaddr, size_t size, int *ret)
{
struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
if (mem && vaddr >= mem->virt_base && vaddr + size <=
(mem->virt_base + (mem->size << PAGE_SHIFT))) {
unsigned long off = vma->vm_pgoff;
int start = (vaddr - mem->virt_base) >> PAGE_SHIFT;
int user_count = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
int count = size >> PAGE_SHIFT;
*ret = -ENXIO;
if (off < count && user_count <= count - off) {
unsigned pfn = mem->pfn_base + start + off;
*ret = remap_pfn_range(vma, vma->vm_start, pfn,
user_count << PAGE_SHIFT,
vma->vm_page_prot);
}
return 1;
}
return 0;
}
EXPORT_SYMBOL(dma_mmap_from_coherent);
#endif

View File

@ -54,6 +54,8 @@ static LIST_HEAD(wakeup_sources);
static DECLARE_WAIT_QUEUE_HEAD(wakeup_count_wait_queue);
static ktime_t last_read_time;
/**
* wakeup_source_prepare - Prepare a new wakeup source for initialization.
* @ws: Wakeup source to prepare.
@ -372,6 +374,20 @@ int device_set_wakeup_enable(struct device *dev, bool enable)
}
EXPORT_SYMBOL_GPL(device_set_wakeup_enable);
/**
* wakeup_source_not_registered - validate the given wakeup source.
* @ws: Wakeup source to be validated.
*/
static bool wakeup_source_not_registered(struct wakeup_source *ws)
{
/*
* Use timer struct to check if the given source is initialized
* by wakeup_source_add.
*/
return ws->timer.function != pm_wakeup_timer_fn ||
ws->timer.data != (unsigned long)ws;
}
/*
* The functions below use the observation that each wakeup event starts a
* period in which the system should not be suspended. The moment this period
@ -412,6 +428,10 @@ static void wakeup_source_activate(struct wakeup_source *ws)
{
unsigned int cec;
if (WARN(wakeup_source_not_registered(ws),
"unregistered wakeup source\n"))
return;
/*
* active wakeup source should bring the system
* out of PM_SUSPEND_FREEZE state
@ -789,10 +809,15 @@ bool pm_wakeup_pending(void)
bool pm_get_wakeup_count(unsigned int *count, bool block)
{
unsigned int cnt, inpr;
unsigned long flags;
if (block) {
DEFINE_WAIT(wait);
spin_lock_irqsave(&events_lock, flags);
last_read_time = ktime_get();
spin_unlock_irqrestore(&events_lock, flags);
for (;;) {
prepare_to_wait(&wakeup_count_wait_queue, &wait,
TASK_INTERRUPTIBLE);
@ -824,6 +849,7 @@ bool pm_save_wakeup_count(unsigned int count)
{
unsigned int cnt, inpr;
unsigned long flags;
struct wakeup_source *ws;
events_check_enabled = false;
spin_lock_irqsave(&events_lock, flags);
@ -831,6 +857,15 @@ bool pm_save_wakeup_count(unsigned int count)
if (cnt == count && inpr == 0) {
saved_count = count;
events_check_enabled = true;
} else {
rcu_read_lock();
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
if (ws->active ||
ktime_compare(ws->last_time, last_read_time) > 0) {
ws->wakeup_count++;
}
}
rcu_read_unlock();
}
spin_unlock_irqrestore(&events_lock, flags);
return events_check_enabled;

View File

@ -18,20 +18,36 @@
#include <linux/module.h>
#include <linux/device-mapper.h>
#include <linux/reboot.h>
#include <crypto/hash.h>
#define DM_MSG_PREFIX "verity"
#define DM_VERITY_ENV_LENGTH 42
#define DM_VERITY_ENV_VAR_NAME "VERITY_ERR_BLOCK_NR"
#define DM_VERITY_IO_VEC_INLINE 16
#define DM_VERITY_MEMPOOL_SIZE 4
#define DM_VERITY_DEFAULT_PREFETCH_SIZE 262144
#define DM_VERITY_MAX_LEVELS 63
#define DM_VERITY_MAX_CORRUPTED_ERRS 100
static unsigned dm_verity_prefetch_cluster = DM_VERITY_DEFAULT_PREFETCH_SIZE;
module_param_named(prefetch_cluster, dm_verity_prefetch_cluster, uint, S_IRUGO | S_IWUSR);
enum verity_mode {
DM_VERITY_MODE_EIO = 0,
DM_VERITY_MODE_LOGGING = 1,
DM_VERITY_MODE_RESTART = 2
};
enum verity_block_type {
DM_VERITY_BLOCK_TYPE_DATA,
DM_VERITY_BLOCK_TYPE_METADATA
};
struct dm_verity {
struct dm_dev *data_dev;
struct dm_dev *hash_dev;
@ -54,6 +70,8 @@ struct dm_verity {
unsigned digest_size; /* digest size for the current hash algorithm */
unsigned shash_descsize;/* the size of temporary space for crypto */
int hash_failed; /* set to 1 if hash of any block failed */
enum verity_mode mode; /* mode for handling verification errors */
unsigned corrupted_errs;/* Number of errors for corrupted blocks */
mempool_t *vec_mempool; /* mempool of bio vector */
@ -179,6 +197,54 @@ static void verity_hash_at_level(struct dm_verity *v, sector_t block, int level,
*offset = idx << (v->hash_dev_block_bits - v->hash_per_block_bits);
}
/*
* Handle verification errors.
*/
static int verity_handle_err(struct dm_verity *v, enum verity_block_type type,
unsigned long long block)
{
char verity_env[DM_VERITY_ENV_LENGTH];
char *envp[] = { verity_env, NULL };
const char *type_str = "";
struct mapped_device *md = dm_table_get_md(v->ti->table);
if (v->corrupted_errs >= DM_VERITY_MAX_CORRUPTED_ERRS)
goto out;
++v->corrupted_errs;
switch (type) {
case DM_VERITY_BLOCK_TYPE_DATA:
type_str = "data";
break;
case DM_VERITY_BLOCK_TYPE_METADATA:
type_str = "metadata";
break;
default:
BUG();
}
DMERR_LIMIT("%s: %s block %llu is corrupted", v->data_dev->name,
type_str, block);
if (v->corrupted_errs == DM_VERITY_MAX_CORRUPTED_ERRS)
DMERR("%s: reached maximum errors", v->data_dev->name);
snprintf(verity_env, DM_VERITY_ENV_LENGTH, "%s=%d,%llu",
DM_VERITY_ENV_VAR_NAME, type, block);
kobject_uevent_env(&disk_to_dev(dm_disk(md))->kobj, KOBJ_CHANGE, envp);
out:
if (v->mode == DM_VERITY_MODE_LOGGING)
return 0;
if (v->mode == DM_VERITY_MODE_RESTART)
kernel_restart("dm-verity device corrupted");
return 1;
}
/*
* Verify hash of a metadata block pertaining to the specified data block
* ("block" argument) at a specified level ("level" argument).
@ -256,11 +322,13 @@ static int verity_verify_level(struct dm_verity_io *io, sector_t block,
goto release_ret_r;
}
if (unlikely(memcmp(result, io_want_digest(v, io), v->digest_size))) {
DMERR_LIMIT("metadata block %llu is corrupted",
(unsigned long long)hash_block);
v->hash_failed = 1;
r = -EIO;
goto release_ret_r;
if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_METADATA,
hash_block)) {
r = -EIO;
goto release_ret_r;
}
} else
aux->hash_verified = 1;
}
@ -377,10 +445,11 @@ test_block_hash:
return r;
}
if (unlikely(memcmp(result, io_want_digest(v, io), v->digest_size))) {
DMERR_LIMIT("data block %llu is corrupted",
(unsigned long long)(io->block + b));
v->hash_failed = 1;
return -EIO;
if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA,
io->block + b))
return -EIO;
}
}
BUG_ON(vector != io->io_vec_size);
@ -689,8 +758,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
goto bad;
}
if (argc != 10) {
ti->error = "Invalid argument count: exactly 10 arguments required";
if (argc < 10 || argc > 11) {
ti->error = "Invalid argument count: 10-11 arguments required";
r = -EINVAL;
goto bad;
}
@ -811,6 +880,17 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
}
}
if (argc > 10) {
if (sscanf(argv[10], "%d%c", &num, &dummy) != 1 ||
num < DM_VERITY_MODE_EIO ||
num > DM_VERITY_MODE_RESTART) {
ti->error = "Invalid mode";
r = -EINVAL;
goto bad;
}
v->mode = num;
}
v->hash_per_block_bits =
fls((1 << v->hash_dev_block_bits) / v->digest_size) - 1;

View File

@ -4089,42 +4089,7 @@ static void mmc_blk_remove(struct mmc_card *card)
#endif
}
static void mmc_blk_shutdown(struct mmc_card *card)
{
struct mmc_blk_data *part_md;
struct mmc_blk_data *md = mmc_get_drvdata(card);
int rc;
/* Silent the block layer */
if (md) {
rc = mmc_queue_suspend(&md->queue, 1);
if (rc)
goto suspend_error;
list_for_each_entry(part_md, &md->part, part) {
rc = mmc_queue_suspend(&part_md->queue, 1);
if (rc)
goto suspend_error;
}
}
/* send power off notification */
if (mmc_card_mmc(card)) {
mmc_rpm_hold(card->host, &card->dev);
mmc_claim_host(card->host);
mmc_stop_bkops(card);
mmc_release_host(card->host);
mmc_send_pon(card);
mmc_rpm_release(card->host, &card->dev);
}
return;
suspend_error:
pr_err("%s: mmc_queue_suspend returned error = %d",
mmc_hostname(card->host), rc);
}
#ifdef CONFIG_PM
static int mmc_blk_suspend(struct mmc_card *card)
static int _mmc_blk_suspend(struct mmc_card *card)
{
struct mmc_blk_data *part_md;
struct mmc_blk_data *md = mmc_get_drvdata(card);
@ -4151,6 +4116,17 @@ static int mmc_blk_suspend(struct mmc_card *card)
return rc;
}
static void mmc_blk_shutdown(struct mmc_card *card)
{
_mmc_blk_suspend(card);
}
#ifdef CONFIG_PM
static int mmc_blk_suspend(struct mmc_card *card)
{
return _mmc_blk_suspend(card);
}
static int mmc_blk_resume(struct mmc_card *card)
{
struct mmc_blk_data *part_md;

View File

@ -3028,12 +3028,17 @@ static void mmc_test_remove(struct mmc_card *card)
mmc_test_free_dbgfs_file(card);
}
static void mmc_test_shutdown(struct mmc_card *card)
{
}
static struct mmc_driver mmc_driver = {
.drv = {
.name = "mmc_test",
},
.probe = mmc_test_probe,
.remove = mmc_test_remove,
.shutdown = mmc_test_shutdown,
};
static int __init mmc_test_init(void)

View File

@ -127,19 +127,18 @@ static void mmc_bus_shutdown(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
struct mmc_card *card = mmc_dev_to_card(dev);
struct mmc_host *host = card->host;
int ret;
if (!drv) {
pr_debug("%s: %s: drv is NULL\n", dev_name(dev), __func__);
return;
}
if (!card) {
pr_debug("%s: %s: card is NULL\n", dev_name(dev), __func__);
return;
}
if (drv->shutdown)
if (dev->driver && drv->shutdown)
drv->shutdown(card);
if (host->bus_ops->shutdown) {
ret = host->bus_ops->shutdown(host);
if (ret)
pr_warn("%s: error %d during shutdown\n",
mmc_hostname(host), ret);
}
}
#ifdef CONFIG_PM_SLEEP
@ -267,7 +266,7 @@ static struct bus_type mmc_bus_type = {
.uevent = mmc_bus_uevent,
.probe = mmc_bus_probe,
.remove = mmc_bus_remove,
.shutdown = mmc_bus_shutdown,
.shutdown = mmc_bus_shutdown,
.pm = &mmc_bus_pm_ops,
};

View File

@ -4014,60 +4014,6 @@ int mmc_flush_cache(struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_flush_cache);
/*
* Turn the cache ON/OFF.
* Turning the cache OFF shall trigger flushing of the data
* to the non-volatile storage.
* This function should be called with host claimed
*/
int mmc_cache_ctrl(struct mmc_host *host, u8 enable)
{
struct mmc_card *card = host->card;
unsigned int timeout;
int err = 0, rc;
BUG_ON(!card);
timeout = card->ext_csd.generic_cmd6_time;
if (!(host->caps2 & MMC_CAP2_CACHE_CTRL) ||
mmc_card_is_removable(host) ||
(card->quirks & MMC_QUIRK_CACHE_DISABLE))
return err;
if (card && mmc_card_mmc(card) &&
(card->ext_csd.cache_size > 0)) {
enable = !!enable;
if (card->ext_csd.cache_ctrl ^ enable) {
if (!enable)
timeout = MMC_FLUSH_REQ_TIMEOUT_MS;
err = mmc_switch_ignore_timeout(card,
EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_CACHE_CTRL, enable, timeout);
if (err == -ETIMEDOUT && !enable) {
pr_err("%s:cache disable operation timeout\n",
mmc_hostname(card->host));
rc = mmc_interrupt_hpi(card);
if (rc)
pr_err("%s: mmc_interrupt_hpi() failed (%d)\n",
mmc_hostname(host), rc);
} else if (err) {
pr_err("%s: cache %s error %d\n",
mmc_hostname(card->host),
enable ? "on" : "off",
err);
} else {
card->ext_csd.cache_ctrl = enable;
}
}
}
return err;
}
EXPORT_SYMBOL(mmc_cache_ctrl);
#ifdef CONFIG_PM
/**

View File

@ -26,6 +26,7 @@ struct mmc_bus_ops {
int (*power_restore)(struct mmc_host *);
int (*alive)(struct mmc_host *);
int (*change_bus_speed)(struct mmc_host *, unsigned long *);
int (*shutdown)(struct mmc_host *);
};
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops);

View File

@ -630,6 +630,8 @@ void mmc_of_parse(struct mmc_host *host)
host->caps |= MMC_CAP_POWER_OFF_CARD;
if (of_find_property(np, "cap-sdio-irq", &len))
host->caps |= MMC_CAP_SDIO_IRQ;
if (of_find_property(np, "full-pwr-cycle", &len))
host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE;
if (of_find_property(np, "keep-power-in-suspend", &len))
host->pm_caps |= MMC_PM_KEEP_POWER;
if (of_find_property(np, "enable-sdio-wakeup", &len))

View File

@ -1627,11 +1627,9 @@ reinit:
}
/*
* If the host supports the power_off_notify capability then
* set the notification byte in the ext_csd register of device
* Enable power_off_notification byte in the ext_csd register
*/
if ((host->caps2 & MMC_CAP2_POWEROFF_NOTIFY) &&
(card->ext_csd.rev >= 6)) {
if (card->ext_csd.rev >= 6) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_POWER_OFF_NOTIFICATION,
EXT_CSD_POWER_ON,
@ -1911,12 +1909,11 @@ static void mmc_detect(struct mmc_host *host)
}
}
/*
* Suspend callback from host.
*/
static int mmc_suspend(struct mmc_host *host)
static int _mmc_suspend(struct mmc_host *host, bool is_suspend)
{
int err = 0;
unsigned int notify_type = is_suspend ? EXT_CSD_POWER_OFF_SHORT :
EXT_CSD_POWER_OFF_LONG;
BUG_ON(!host);
BUG_ON(!host->card);
@ -1930,11 +1927,14 @@ static int mmc_suspend(struct mmc_host *host)
*/
mmc_disable_clk_scaling(host);
err = mmc_cache_ctrl(host, 0);
err = mmc_flush_cache(host->card);
if (err)
goto out;
if (mmc_card_can_sleep(host))
if (mmc_can_poweroff_notify(host->card) &&
((host->caps2 & MMC_CAP2_FULL_PWR_CYCLE) || !is_suspend))
err = mmc_poweroff_notify(host->card, notify_type);
else if (mmc_card_can_sleep(host))
err = mmc_card_sleep(host);
else if (!mmc_host_is_spi(host))
err = mmc_deselect_cards(host);
@ -1945,6 +1945,22 @@ out:
return err;
}
/*
* Suspend callback from host.
*/
static int mmc_suspend(struct mmc_host *host)
{
return _mmc_suspend(host, true);
}
/*
* Shutdown callback
*/
static int mmc_shutdown(struct mmc_host *host)
{
return _mmc_suspend(host, false);
}
/*
* Resume callback from host.
*
@ -2070,6 +2086,7 @@ static const struct mmc_bus_ops mmc_ops = {
.power_restore = mmc_power_restore,
.alive = mmc_alive,
.change_bus_speed = mmc_change_bus_speed,
.shutdown = mmc_shutdown,
};
static const struct mmc_bus_ops mmc_ops_unsafe = {
@ -2082,6 +2099,7 @@ static const struct mmc_bus_ops mmc_ops_unsafe = {
.power_restore = mmc_power_restore,
.alive = mmc_alive,
.change_bus_speed = mmc_change_bus_speed,
.shutdown = mmc_shutdown,
};
static void mmc_attach_bus_ops(struct mmc_host *host)

View File

@ -930,7 +930,7 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card,
if (!err) {
if (retries > 1) {
printk(KERN_WARNING
"%s: recovered\n",
"%s: recovered\n",
mmc_hostname(host));
}
break;
@ -1302,6 +1302,7 @@ static const struct mmc_bus_ops mmc_sd_ops = {
.power_restore = mmc_sd_power_restore,
.alive = mmc_sd_alive,
.change_bus_speed = mmc_sd_change_bus_speed,
.shutdown = mmc_sd_suspend,
};
static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
@ -1312,6 +1313,7 @@ static const struct mmc_bus_ops mmc_sd_ops_unsafe = {
.power_restore = mmc_sd_power_restore,
.alive = mmc_sd_alive,
.change_bus_speed = mmc_sd_change_bus_speed,
.shutdown = mmc_sd_suspend,
};
static void mmc_sd_attach_bus_ops(struct mmc_host *host)

View File

@ -3714,7 +3714,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)
msm_host->mmc->caps2 |= (MMC_CAP2_BOOTPART_NOACC |
MMC_CAP2_DETECT_ON_ERR);
msm_host->mmc->caps2 |= MMC_CAP2_CACHE_CTRL;
msm_host->mmc->caps2 |= MMC_CAP2_POWEROFF_NOTIFY;
msm_host->mmc->caps2 |= MMC_CAP2_FULL_PWR_CYCLE;
msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE;
msm_host->mmc->caps2 |= MMC_CAP2_STOP_REQUEST;
msm_host->mmc->caps2 |= MMC_CAP2_ASYNC_SDIO_IRQ_4BIT_MODE;

View File

@ -20,31 +20,6 @@ config ASHMEM
It is, in theory, a good memory allocator for low-memory devices,
because it can discard shared memory units when under memory pressure.
config ANDROID_LOGGER
tristate "Android log driver"
default n
---help---
This adds support for system-wide logging using four log buffers.
These are:
1: main
2: events
3: radio
4: system
Log reading and writing is performed via normal Linux reads and
optimized writes. This optimization avoids logging having too
much overhead in the system.
config LOGCAT_SIZE
int "Adjust android log buffer sizes"
default 256
depends on ANDROID_LOGGER
help
Set logger buffer size. Enter a number greater than zero.
Any value less than 256 is recommended. Reduce value to save kernel static memory size.
config ANDROID_TIMED_OUTPUT
bool "Timed output class driver"
default y
@ -69,15 +44,6 @@ config ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
/sys/module/lowmemorykiller/parameters/adj and convert them
to oom_score_adj values.
config ANDROID_INTF_ALARM_DEV
bool "Android alarm driver"
depends on RTC_CLASS
default n
---help---
Provides non-wakeup and rtc backed wakeup alarms based on rtc or
elapsed realtime, and a non-wakeup alarm on the monotonic clock.
Also exports the alarm interface to user-space.
config SYNC
bool "Synchronization framework"
default n

View File

@ -4,11 +4,9 @@ obj-y += ion/
obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger/
obj-$(CONFIG_ASHMEM) += ashmem.o
obj-$(CONFIG_ANDROID_LOGGER) += logger.o
obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
obj-$(CONFIG_ANDROID_INTF_ALARM_DEV) += alarm-dev.o
obj-$(CONFIG_SYNC) += sync.o
obj-$(CONFIG_SW_SYNC) += sw_sync.o
obj-$(CONFIG_ONESHOT_SYNC) += oneshot_sync.o

View File

@ -1,462 +0,0 @@
/* drivers/rtc/alarm-dev.c
*
* Copyright (C) 2007-2009 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <linux/time.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/alarmtimer.h>
#include "android_alarm.h"
#define ANDROID_ALARM_PRINT_INFO (1U << 0)
#define ANDROID_ALARM_PRINT_IO (1U << 1)
#define ANDROID_ALARM_PRINT_INT (1U << 2)
static int debug_mask = ANDROID_ALARM_PRINT_INFO;
module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
#define alarm_dbg(debug_level_mask, fmt, ...) \
do { \
if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) \
pr_info(fmt, ##__VA_ARGS__); \
} while (0)
#define ANDROID_ALARM_WAKEUP_MASK ( \
ANDROID_ALARM_RTC_WAKEUP_MASK | \
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK | \
ANDROID_ALARM_RTC_POWEROFF_WAKEUP_MASK)
static int alarm_opened;
static DEFINE_SPINLOCK(alarm_slock);
static DEFINE_MUTEX(alarm_mutex);
static struct wakeup_source alarm_wake_lock;
static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue);
static uint32_t alarm_pending;
static uint32_t alarm_enabled;
static uint32_t wait_pending;
struct devalarm {
union {
struct hrtimer hrt;
struct alarm alrm;
} u;
enum android_alarm_type type;
};
static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT];
static int is_wakeup(enum android_alarm_type type)
{
return (type == ANDROID_ALARM_RTC_WAKEUP ||
type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP ||
type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP);
}
static void devalarm_start(struct devalarm *alrm, ktime_t exp)
{
if (is_wakeup(alrm->type))
alarm_start(&alrm->u.alrm, exp);
else
hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS);
}
static int devalarm_try_to_cancel(struct devalarm *alrm)
{
if (is_wakeup(alrm->type))
return alarm_try_to_cancel(&alrm->u.alrm);
return hrtimer_try_to_cancel(&alrm->u.hrt);
}
static void devalarm_cancel(struct devalarm *alrm)
{
if (is_wakeup(alrm->type))
alarm_cancel(&alrm->u.alrm);
else
hrtimer_cancel(&alrm->u.hrt);
}
static void alarm_clear(enum android_alarm_type alarm_type, struct timespec *ts)
{
uint32_t alarm_type_mask = 1U << alarm_type;
unsigned long flags;
mutex_lock(&alarm_mutex);
spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm %d clear\n", alarm_type);
devalarm_try_to_cancel(&alarms[alarm_type]);
if (alarm_pending) {
alarm_pending &= ~alarm_type_mask;
if (!alarm_pending && !wait_pending)
__pm_relax(&alarm_wake_lock);
}
alarm_enabled &= ~alarm_type_mask;
spin_unlock_irqrestore(&alarm_slock, flags);
if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP)
set_power_on_alarm(ts->tv_sec, 0);
mutex_unlock(&alarm_mutex);
}
static void alarm_set(enum android_alarm_type alarm_type,
struct timespec *ts)
{
uint32_t alarm_type_mask = 1U << alarm_type;
unsigned long flags;
mutex_lock(&alarm_mutex);
spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm %d set %ld.%09ld\n",
alarm_type, ts->tv_sec, ts->tv_nsec);
alarm_enabled |= alarm_type_mask;
devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts));
spin_unlock_irqrestore(&alarm_slock, flags);
if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP)
set_power_on_alarm(ts->tv_sec, 1);
mutex_unlock(&alarm_mutex);
}
static int alarm_wait(void)
{
unsigned long flags;
int rv = 0;
spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm wait\n");
if (!alarm_pending && wait_pending) {
__pm_relax(&alarm_wake_lock);
wait_pending = 0;
}
spin_unlock_irqrestore(&alarm_slock, flags);
rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
if (rv)
return rv;
spin_lock_irqsave(&alarm_slock, flags);
rv = alarm_pending;
wait_pending = 1;
alarm_pending = 0;
spin_unlock_irqrestore(&alarm_slock, flags);
return rv;
}
static int alarm_set_rtc(struct timespec *ts)
{
struct rtc_time new_rtc_tm;
struct rtc_device *rtc_dev;
unsigned long flags;
int rv = 0;
rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
rtc_dev = alarmtimer_get_rtcdev();
rv = do_settimeofday(ts);
if (rv < 0)
return rv;
if (rtc_dev)
rv = rtc_set_time(rtc_dev, &new_rtc_tm);
spin_lock_irqsave(&alarm_slock, flags);
alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
wake_up(&alarm_wait_queue);
spin_unlock_irqrestore(&alarm_slock, flags);
return rv;
}
static int alarm_get_time(enum android_alarm_type alarm_type,
struct timespec *ts)
{
int rv = 0;
switch (alarm_type) {
case ANDROID_ALARM_RTC_WAKEUP:
case ANDROID_ALARM_RTC:
case ANDROID_ALARM_RTC_POWEROFF_WAKEUP:
getnstimeofday(ts);
break;
case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
case ANDROID_ALARM_ELAPSED_REALTIME:
get_monotonic_boottime(ts);
break;
case ANDROID_ALARM_SYSTEMTIME:
ktime_get_ts(ts);
break;
default:
rv = -EINVAL;
}
return rv;
}
static long alarm_do_ioctl(struct file *file, unsigned int cmd,
struct timespec *ts)
{
int rv = 0;
unsigned long flags;
enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
return -EINVAL;
if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
if ((file->f_flags & O_ACCMODE) == O_RDONLY)
return -EPERM;
if (file->private_data == NULL &&
cmd != ANDROID_ALARM_SET_RTC) {
spin_lock_irqsave(&alarm_slock, flags);
if (alarm_opened) {
spin_unlock_irqrestore(&alarm_slock, flags);
return -EBUSY;
}
alarm_opened = 1;
file->private_data = (void *)1;
spin_unlock_irqrestore(&alarm_slock, flags);
}
}
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_CLEAR(0):
alarm_clear(alarm_type, ts);
break;
case ANDROID_ALARM_SET(0):
alarm_set(alarm_type, ts);
break;
case ANDROID_ALARM_SET_AND_WAIT(0):
alarm_set(alarm_type, ts);
/* fall though */
case ANDROID_ALARM_WAIT:
rv = alarm_wait();
break;
case ANDROID_ALARM_SET_RTC:
rv = alarm_set_rtc(ts);
break;
case ANDROID_ALARM_GET_TIME(0):
rv = alarm_get_time(alarm_type, ts);
break;
default:
rv = -EINVAL;
}
return rv;
}
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct timespec ts;
int rv;
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_SET_AND_WAIT(0):
case ANDROID_ALARM_SET(0):
case ANDROID_ALARM_SET_RTC:
case ANDROID_ALARM_CLEAR(0):
if (copy_from_user(&ts, (void __user *)arg, sizeof(ts)))
return -EFAULT;
break;
}
rv = alarm_do_ioctl(file, cmd, &ts);
if (rv)
return rv;
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_GET_TIME(0):
if (copy_to_user((void __user *)arg, &ts, sizeof(ts)))
return -EFAULT;
break;
}
return 0;
}
#ifdef CONFIG_COMPAT
static long alarm_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct timespec ts;
int rv;
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0):
case ANDROID_ALARM_SET_COMPAT(0):
case ANDROID_ALARM_SET_RTC_COMPAT:
if (compat_get_timespec(&ts, (void __user *)arg))
return -EFAULT;
/* fall through */
case ANDROID_ALARM_GET_TIME_COMPAT(0):
cmd = ANDROID_ALARM_COMPAT_TO_NORM(cmd);
break;
}
rv = alarm_do_ioctl(file, cmd, &ts);
if (rv)
return rv;
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_GET_TIME(0): /* NOTE: we modified cmd above */
if (compat_put_timespec(&ts, (void __user *)arg))
return -EFAULT;
break;
}
return 0;
}
#endif
static int alarm_open(struct inode *inode, struct file *file)
{
file->private_data = NULL;
return 0;
}
static int alarm_release(struct inode *inode, struct file *file)
{
int i;
unsigned long flags;
spin_lock_irqsave(&alarm_slock, flags);
if (file->private_data) {
for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
uint32_t alarm_type_mask = 1U << i;
if (alarm_enabled & alarm_type_mask) {
alarm_dbg(INFO,
"%s: clear alarm, pending %d\n",
__func__,
!!(alarm_pending & alarm_type_mask));
alarm_enabled &= ~alarm_type_mask;
}
spin_unlock_irqrestore(&alarm_slock, flags);
devalarm_cancel(&alarms[i]);
spin_lock_irqsave(&alarm_slock, flags);
}
if (alarm_pending | wait_pending) {
if (alarm_pending)
alarm_dbg(INFO, "%s: clear pending alarms %x\n",
__func__, alarm_pending);
__pm_relax(&alarm_wake_lock);
wait_pending = 0;
alarm_pending = 0;
}
alarm_opened = 0;
}
spin_unlock_irqrestore(&alarm_slock, flags);
return 0;
}
static void devalarm_triggered(struct devalarm *alarm)
{
unsigned long flags;
uint32_t alarm_type_mask = 1U << alarm->type;
alarm_dbg(INT, "%s: type %d\n", __func__, alarm->type);
spin_lock_irqsave(&alarm_slock, flags);
if (alarm_enabled & alarm_type_mask) {
__pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */
alarm_enabled &= ~alarm_type_mask;
alarm_pending |= alarm_type_mask;
wake_up(&alarm_wait_queue);
}
spin_unlock_irqrestore(&alarm_slock, flags);
}
static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt)
{
struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt);
devalarm_triggered(devalrm);
return HRTIMER_NORESTART;
}
static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm,
ktime_t now)
{
struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm);
devalarm_triggered(devalrm);
return ALARMTIMER_NORESTART;
}
static const struct file_operations alarm_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = alarm_ioctl,
.open = alarm_open,
.release = alarm_release,
#ifdef CONFIG_COMPAT
.compat_ioctl = alarm_compat_ioctl,
#endif
};
static struct miscdevice alarm_device = {
.minor = MISC_DYNAMIC_MINOR,
.name = "alarm",
.fops = &alarm_fops,
};
static int __init alarm_dev_init(void)
{
int err;
int i;
err = misc_register(&alarm_device);
if (err)
return err;
alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm,
ALARM_REALTIME, devalarm_alarmhandler);
hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt,
CLOCK_REALTIME, HRTIMER_MODE_ABS);
alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm,
ALARM_BOOTTIME, devalarm_alarmhandler);
hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt,
CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt,
CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
alarm_init(&alarms[ANDROID_ALARM_RTC_POWEROFF_WAKEUP].u.alrm,
ALARM_REALTIME, devalarm_alarmhandler);
for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
alarms[i].type = i;
if (!is_wakeup(i))
alarms[i].u.hrt.function = devalarm_hrthandler;
}
wakeup_source_init(&alarm_wake_lock, "alarm");
power_on_alarm_init();
return 0;
}
static void __exit alarm_dev_exit(void)
{
misc_deregister(&alarm_device);
wakeup_source_trash(&alarm_wake_lock);
}
module_init(alarm_dev_init);
module_exit(alarm_dev_exit);

View File

@ -1,41 +0,0 @@
/* include/linux/android_alarm.h
*
* Copyright (C) 2006-2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _LINUX_ANDROID_ALARM_H
#define _LINUX_ANDROID_ALARM_H
#include <linux/compat.h>
#include <linux/ioctl.h>
#include "uapi/android_alarm.h"
#ifdef CONFIG_COMPAT
#define ANDROID_ALARM_SET_COMPAT(type) ALARM_IOW(2, type, \
struct compat_timespec)
#define ANDROID_ALARM_SET_AND_WAIT_COMPAT(type) ALARM_IOW(3, type, \
struct compat_timespec)
#define ANDROID_ALARM_GET_TIME_COMPAT(type) ALARM_IOW(4, type, \
struct compat_timespec)
#define ANDROID_ALARM_SET_RTC_COMPAT _IOW('a', 5, \
struct compat_timespec)
#define ANDROID_ALARM_IOCTL_NR(cmd) (_IOC_NR(cmd) & ((1<<4)-1))
#define ANDROID_ALARM_COMPAT_TO_NORM(cmd) \
ALARM_IOW(ANDROID_ALARM_IOCTL_NR(cmd), \
ANDROID_ALARM_IOCTL_TO_TYPE(cmd), \
struct timespec)
#endif
#endif

View File

@ -376,7 +376,7 @@ static int ashmem_shrink(struct shrinker *s, struct shrink_control *sc)
loff_t start = range->pgstart * PAGE_SIZE;
loff_t end = (range->pgend + 1) * PAGE_SIZE;
do_fallocate(range->asma->file,
range->asma->file->f_op->fallocate(range->asma->file,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
start, end - start);
range->purged = ASHMEM_WAS_PURGED;

View File

@ -429,7 +429,8 @@ static void fiq_debugger_help(struct fiq_debugger_state *state)
" pc PC status\n"
" regs Register dump\n"
" allregs Extended Register dump\n"
" bt Stack trace\n"
" bt Stack trace\n");
fiq_debugger_printf(&state->output,
" reboot [<c>] Reboot with command <c>\n"
" reset [<c>] Hard reset with command <c>\n"
" irqs Interupt status\n"

View File

@ -1,858 +0,0 @@
/*
* drivers/misc/logger.c
*
* A Logging Subsystem
*
* Copyright (C) 2007-2008 Google, Inc.
*
* Robert Love <rlove@google.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) "logger: " fmt
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
#include <linux/aio.h>
#include "logger.h"
#include <asm/ioctls.h>
#ifndef CONFIG_LOGCAT_SIZE
#define CONFIG_LOGCAT_SIZE 256
#endif
/**
* struct logger_log - represents a specific log, such as 'main' or 'radio'
* @buffer: The actual ring buffer
* @misc: The "misc" device representing the log
* @wq: The wait queue for @readers
* @readers: This log's readers
* @mutex: The mutex that protects the @buffer
* @w_off: The current write head offset
* @head: The head, or location that readers start reading at.
* @size: The size of the log
* @logs: The list of log channels
*
* This structure lives from module insertion until module removal, so it does
* not need additional reference counting. The structure is protected by the
* mutex 'mutex'.
*/
struct logger_log {
unsigned char *buffer;
struct miscdevice misc;
wait_queue_head_t wq;
struct list_head readers;
struct mutex mutex;
size_t w_off;
size_t head;
size_t size;
struct list_head logs;
};
static LIST_HEAD(log_list);
/**
* struct logger_reader - a logging device open for reading
* @log: The associated log
* @list: The associated entry in @logger_log's list
* @r_off: The current read head offset.
* @r_all: Reader can read all entries
* @r_ver: Reader ABI version
*
* This object lives from open to release, so we don't need additional
* reference counting. The structure is protected by log->mutex.
*/
struct logger_reader {
struct logger_log *log;
struct list_head list;
size_t r_off;
bool r_all;
int r_ver;
};
/* logger_offset - returns index 'n' into the log via (optimized) modulus */
static size_t logger_offset(struct logger_log *log, size_t n)
{
return n & (log->size - 1);
}
/*
* file_get_log - Given a file structure, return the associated log
*
* This isn't aesthetic. We have several goals:
*
* 1) Need to quickly obtain the associated log during an I/O operation
* 2) Readers need to maintain state (logger_reader)
* 3) Writers need to be very fast (open() should be a near no-op)
*
* In the reader case, we can trivially go file->logger_reader->logger_log.
* For a writer, we don't want to maintain a logger_reader, so we just go
* file->logger_log. Thus what file->private_data points at depends on whether
* or not the file was opened for reading. This function hides that dirtiness.
*/
static inline struct logger_log *file_get_log(struct file *file)
{
if (file->f_mode & FMODE_READ) {
struct logger_reader *reader = file->private_data;
return reader->log;
} else
return file->private_data;
}
/*
* get_entry_header - returns a pointer to the logger_entry header within
* 'log' starting at offset 'off'. A temporary logger_entry 'scratch' must
* be provided. Typically the return value will be a pointer within
* 'logger->buf'. However, a pointer to 'scratch' may be returned if
* the log entry spans the end and beginning of the circular buffer.
*/
static struct logger_entry *get_entry_header(struct logger_log *log,
size_t off, struct logger_entry *scratch)
{
size_t len = min(sizeof(struct logger_entry), log->size - off);
if (len != sizeof(struct logger_entry)) {
memcpy(((void *) scratch), log->buffer + off, len);
memcpy(((void *) scratch) + len, log->buffer,
sizeof(struct logger_entry) - len);
return scratch;
}
return (struct logger_entry *) (log->buffer + off);
}
/*
* get_entry_msg_len - Grabs the length of the message of the entry
* starting from from 'off'.
*
* An entry length is 2 bytes (16 bits) in host endian order.
* In the log, the length does not include the size of the log entry structure.
* This function returns the size including the log entry structure.
*
* Caller needs to hold log->mutex.
*/
static __u32 get_entry_msg_len(struct logger_log *log, size_t off)
{
struct logger_entry scratch;
struct logger_entry *entry;
entry = get_entry_header(log, off, &scratch);
return entry->len;
}
static size_t get_user_hdr_len(int ver)
{
if (ver < 2)
return sizeof(struct user_logger_entry_compat);
else
return sizeof(struct logger_entry);
}
static ssize_t copy_header_to_user(int ver, struct logger_entry *entry,
char __user *buf)
{
void *hdr;
size_t hdr_len;
struct user_logger_entry_compat v1;
if (ver < 2) {
v1.len = entry->len;
v1.__pad = 0;
v1.pid = entry->pid;
v1.tid = entry->tid;
v1.sec = entry->sec;
v1.nsec = entry->nsec;
hdr = &v1;
hdr_len = sizeof(struct user_logger_entry_compat);
} else {
hdr = entry;
hdr_len = sizeof(struct logger_entry);
}
return copy_to_user(buf, hdr, hdr_len);
}
/*
* do_read_log_to_user - reads exactly 'count' bytes from 'log' into the
* user-space buffer 'buf'. Returns 'count' on success.
*
* Caller must hold log->mutex.
*/
static ssize_t do_read_log_to_user(struct logger_log *log,
struct logger_reader *reader,
char __user *buf,
size_t count)
{
struct logger_entry scratch;
struct logger_entry *entry;
size_t len;
size_t msg_start;
/*
* First, copy the header to userspace, using the version of
* the header requested
*/
entry = get_entry_header(log, reader->r_off, &scratch);
if (copy_header_to_user(reader->r_ver, entry, buf))
return -EFAULT;
count -= get_user_hdr_len(reader->r_ver);
buf += get_user_hdr_len(reader->r_ver);
msg_start = logger_offset(log,
reader->r_off + sizeof(struct logger_entry));
/*
* We read from the msg in two disjoint operations. First, we read from
* the current msg head offset up to 'count' bytes or to the end of
* the log, whichever comes first.
*/
len = min(count, log->size - msg_start);
if (copy_to_user(buf, log->buffer + msg_start, len))
return -EFAULT;
/*
* Second, we read any remaining bytes, starting back at the head of
* the log.
*/
if (count != len)
if (copy_to_user(buf + len, log->buffer, count - len))
return -EFAULT;
reader->r_off = logger_offset(log, reader->r_off +
sizeof(struct logger_entry) + count);
return count + get_user_hdr_len(reader->r_ver);
}
/*
* get_next_entry_by_uid - Starting at 'off', returns an offset into
* 'log->buffer' which contains the first entry readable by 'euid'
*/
static size_t get_next_entry_by_uid(struct logger_log *log,
size_t off, kuid_t euid)
{
while (off != log->w_off) {
struct logger_entry *entry;
struct logger_entry scratch;
size_t next_len;
entry = get_entry_header(log, off, &scratch);
if (uid_eq(entry->euid, euid))
return off;
next_len = sizeof(struct logger_entry) + entry->len;
off = logger_offset(log, off + next_len);
}
return off;
}
/*
* logger_read - our log's read() method
*
* Behavior:
*
* - O_NONBLOCK works
* - If there are no log entries to read, blocks until log is written to
* - Atomically reads exactly one log entry
*
* Will set errno to EINVAL if read
* buffer is insufficient to hold next entry.
*/
static ssize_t logger_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
struct logger_reader *reader = file->private_data;
struct logger_log *log = reader->log;
ssize_t ret;
DEFINE_WAIT(wait);
start:
while (1) {
mutex_lock(&log->mutex);
prepare_to_wait(&log->wq, &wait, TASK_INTERRUPTIBLE);
ret = (log->w_off == reader->r_off);
mutex_unlock(&log->mutex);
if (!ret)
break;
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
break;
}
if (signal_pending(current)) {
ret = -EINTR;
break;
}
schedule();
}
finish_wait(&log->wq, &wait);
if (ret)
return ret;
mutex_lock(&log->mutex);
if (!reader->r_all)
reader->r_off = get_next_entry_by_uid(log,
reader->r_off, current_euid());
/* is there still something to read or did we race? */
if (unlikely(log->w_off == reader->r_off)) {
mutex_unlock(&log->mutex);
goto start;
}
/* get the size of the next entry */
ret = get_user_hdr_len(reader->r_ver) +
get_entry_msg_len(log, reader->r_off);
if (count < ret) {
ret = -EINVAL;
goto out;
}
/* get exactly one entry from the log */
ret = do_read_log_to_user(log, reader, buf, ret);
out:
mutex_unlock(&log->mutex);
return ret;
}
/*
* get_next_entry - return the offset of the first valid entry at least 'len'
* bytes after 'off'.
*
* Caller must hold log->mutex.
*/
static size_t get_next_entry(struct logger_log *log, size_t off, size_t len)
{
size_t count = 0;
do {
size_t nr = sizeof(struct logger_entry) +
get_entry_msg_len(log, off);
off = logger_offset(log, off + nr);
count += nr;
} while (count < len);
return off;
}
/*
* is_between - is a < c < b, accounting for wrapping of a, b, and c
* positions in the buffer
*
* That is, if a<b, check for c between a and b
* and if a>b, check for c outside (not between) a and b
*
* |------- a xxxxxxxx b --------|
* c^
*
* |xxxxx b --------- a xxxxxxxxx|
* c^
* or c^
*/
static inline int is_between(size_t a, size_t b, size_t c)
{
if (a < b) {
/* is c between a and b? */
if (a < c && c <= b)
return 1;
} else {
/* is c outside of b through a? */
if (c <= b || a < c)
return 1;
}
return 0;
}
/*
* fix_up_readers - walk the list of all readers and "fix up" any who were
* lapped by the writer; also do the same for the default "start head".
* We do this by "pulling forward" the readers and start head to the first
* entry after the new write head.
*
* The caller needs to hold log->mutex.
*/
static void fix_up_readers(struct logger_log *log, size_t len)
{
size_t old = log->w_off;
size_t new = logger_offset(log, old + len);
struct logger_reader *reader;
if (is_between(old, new, log->head))
log->head = get_next_entry(log, log->head, len);
list_for_each_entry(reader, &log->readers, list)
if (is_between(old, new, reader->r_off))
reader->r_off = get_next_entry(log, reader->r_off, len);
}
/*
* do_write_log - writes 'len' bytes from 'buf' to 'log'
*
* The caller needs to hold log->mutex.
*/
static void do_write_log(struct logger_log *log, const void *buf, size_t count)
{
size_t len;
len = min(count, log->size - log->w_off);
memcpy(log->buffer + log->w_off, buf, len);
if (count != len)
memcpy(log->buffer, buf + len, count - len);
log->w_off = logger_offset(log, log->w_off + count);
}
/*
* do_write_log_user - writes 'len' bytes from the user-space buffer 'buf' to
* the log 'log'
*
* The caller needs to hold log->mutex.
*
* Returns 'count' on success, negative error code on failure.
*/
static ssize_t do_write_log_from_user(struct logger_log *log,
const void __user *buf, size_t count)
{
size_t len;
len = min(count, log->size - log->w_off);
if (len && copy_from_user(log->buffer + log->w_off, buf, len))
return -EFAULT;
if (count != len)
if (copy_from_user(log->buffer, buf + len, count - len))
/*
* Note that by not updating w_off, this abandons the
* portion of the new entry that *was* successfully
* copied, just above. This is intentional to avoid
* message corruption from missing fragments.
*/
return -EFAULT;
log->w_off = logger_offset(log, log->w_off + count);
return count;
}
/*
* logger_aio_write - our write method, implementing support for write(),
* writev(), and aio_write(). Writes are our fast path, and we try to optimize
* them above all else.
*/
static ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
unsigned long nr_segs, loff_t ppos)
{
struct logger_log *log = file_get_log(iocb->ki_filp);
size_t orig;
struct logger_entry header;
struct timespec now;
ssize_t ret = 0;
now = current_kernel_time();
header.pid = current->tgid;
header.tid = current->pid;
header.sec = now.tv_sec;
header.nsec = now.tv_nsec;
header.euid = current_euid();
header.len = min_t(size_t, iocb->ki_left, LOGGER_ENTRY_MAX_PAYLOAD);
header.hdr_size = sizeof(struct logger_entry);
/* null writes succeed, return zero */
if (unlikely(!header.len))
return 0;
mutex_lock(&log->mutex);
orig = log->w_off;
/*
* Fix up any readers, pulling them forward to the first readable
* entry after (what will be) the new write offset. We do this now
* because if we partially fail, we can end up with clobbered log
* entries that encroach on readable buffer.
*/
fix_up_readers(log, sizeof(struct logger_entry) + header.len);
do_write_log(log, &header, sizeof(struct logger_entry));
while (nr_segs-- > 0) {
size_t len;
ssize_t nr;
/* figure out how much of this vector we can keep */
len = min_t(size_t, iov->iov_len, header.len - ret);
/* write out this segment's payload */
nr = do_write_log_from_user(log, iov->iov_base, len);
if (unlikely(nr < 0)) {
log->w_off = orig;
mutex_unlock(&log->mutex);
return nr;
}
iov++;
ret += nr;
}
mutex_unlock(&log->mutex);
/* wake up any blocked readers */
wake_up_interruptible(&log->wq);
return ret;
}
static struct logger_log *get_log_from_minor(int minor)
{
struct logger_log *log;
list_for_each_entry(log, &log_list, logs)
if (log->misc.minor == minor)
return log;
return NULL;
}
/*
* logger_open - the log's open() file operation
*
* Note how near a no-op this is in the write-only case. Keep it that way!
*/
static int logger_open(struct inode *inode, struct file *file)
{
struct logger_log *log;
int ret;
ret = nonseekable_open(inode, file);
if (ret)
return ret;
log = get_log_from_minor(MINOR(inode->i_rdev));
if (!log)
return -ENODEV;
if (file->f_mode & FMODE_READ) {
struct logger_reader *reader;
reader = kmalloc(sizeof(struct logger_reader), GFP_KERNEL);
if (!reader)
return -ENOMEM;
reader->log = log;
reader->r_ver = 1;
reader->r_all = in_egroup_p(inode->i_gid) ||
capable(CAP_SYSLOG);
INIT_LIST_HEAD(&reader->list);
mutex_lock(&log->mutex);
reader->r_off = log->head;
list_add_tail(&reader->list, &log->readers);
mutex_unlock(&log->mutex);
file->private_data = reader;
} else
file->private_data = log;
return 0;
}
/*
* logger_release - the log's release file operation
*
* Note this is a total no-op in the write-only case. Keep it that way!
*/
static int logger_release(struct inode *ignored, struct file *file)
{
if (file->f_mode & FMODE_READ) {
struct logger_reader *reader = file->private_data;
struct logger_log *log = reader->log;
mutex_lock(&log->mutex);
list_del(&reader->list);
mutex_unlock(&log->mutex);
kfree(reader);
}
return 0;
}
/*
* logger_poll - the log's poll file operation, for poll/select/epoll
*
* Note we always return POLLOUT, because you can always write() to the log.
* Note also that, strictly speaking, a return value of POLLIN does not
* guarantee that the log is readable without blocking, as there is a small
* chance that the writer can lap the reader in the interim between poll()
* returning and the read() request.
*/
static unsigned int logger_poll(struct file *file, poll_table *wait)
{
struct logger_reader *reader;
struct logger_log *log;
unsigned int ret = POLLOUT | POLLWRNORM;
if (!(file->f_mode & FMODE_READ))
return ret;
reader = file->private_data;
log = reader->log;
poll_wait(file, &log->wq, wait);
mutex_lock(&log->mutex);
if (!reader->r_all)
reader->r_off = get_next_entry_by_uid(log,
reader->r_off, current_euid());
if (log->w_off != reader->r_off)
ret |= POLLIN | POLLRDNORM;
mutex_unlock(&log->mutex);
return ret;
}
static long logger_set_version(struct logger_reader *reader, void __user *arg)
{
int version;
if (copy_from_user(&version, arg, sizeof(int)))
return -EFAULT;
if ((version < 1) || (version > 2))
return -EINVAL;
reader->r_ver = version;
return 0;
}
static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct logger_log *log = file_get_log(file);
struct logger_reader *reader;
long ret = -EINVAL;
void __user *argp = (void __user *) arg;
mutex_lock(&log->mutex);
switch (cmd) {
case LOGGER_GET_LOG_BUF_SIZE:
ret = log->size;
break;
case LOGGER_GET_LOG_LEN:
if (!(file->f_mode & FMODE_READ)) {
ret = -EBADF;
break;
}
reader = file->private_data;
if (log->w_off >= reader->r_off)
ret = log->w_off - reader->r_off;
else
ret = (log->size - reader->r_off) + log->w_off;
break;
case LOGGER_GET_NEXT_ENTRY_LEN:
if (!(file->f_mode & FMODE_READ)) {
ret = -EBADF;
break;
}
reader = file->private_data;
if (!reader->r_all)
reader->r_off = get_next_entry_by_uid(log,
reader->r_off, current_euid());
if (log->w_off != reader->r_off)
ret = get_user_hdr_len(reader->r_ver) +
get_entry_msg_len(log, reader->r_off);
else
ret = 0;
break;
case LOGGER_FLUSH_LOG:
if (!(file->f_mode & FMODE_WRITE)) {
ret = -EBADF;
break;
}
if (!(in_egroup_p(file->f_dentry->d_inode->i_gid) ||
capable(CAP_SYSLOG))) {
ret = -EPERM;
break;
}
list_for_each_entry(reader, &log->readers, list)
reader->r_off = log->w_off;
log->head = log->w_off;
ret = 0;
break;
case LOGGER_GET_VERSION:
if (!(file->f_mode & FMODE_READ)) {
ret = -EBADF;
break;
}
reader = file->private_data;
ret = reader->r_ver;
break;
case LOGGER_SET_VERSION:
if (!(file->f_mode & FMODE_READ)) {
ret = -EBADF;
break;
}
reader = file->private_data;
ret = logger_set_version(reader, argp);
break;
}
mutex_unlock(&log->mutex);
return ret;
}
static const struct file_operations logger_fops = {
.owner = THIS_MODULE,
.read = logger_read,
.aio_write = logger_aio_write,
.poll = logger_poll,
.unlocked_ioctl = logger_ioctl,
.compat_ioctl = logger_ioctl,
.open = logger_open,
.release = logger_release,
};
/*
* Log size must must be a power of two, and greater than
* (LOGGER_ENTRY_MAX_PAYLOAD + sizeof(struct logger_entry)).
*/
static int __init create_log(char *log_name, int size)
{
int ret = 0;
struct logger_log *log;
unsigned char *buffer;
buffer = vmalloc(size);
if (buffer == NULL)
return -ENOMEM;
log = kzalloc(sizeof(struct logger_log), GFP_KERNEL);
if (log == NULL) {
ret = -ENOMEM;
goto out_free_buffer;
}
log->buffer = buffer;
log->misc.minor = MISC_DYNAMIC_MINOR;
log->misc.name = kstrdup(log_name, GFP_KERNEL);
if (log->misc.name == NULL) {
ret = -ENOMEM;
goto out_free_log;
}
log->misc.fops = &logger_fops;
log->misc.parent = NULL;
init_waitqueue_head(&log->wq);
INIT_LIST_HEAD(&log->readers);
mutex_init(&log->mutex);
log->w_off = 0;
log->head = 0;
log->size = size;
INIT_LIST_HEAD(&log->logs);
list_add_tail(&log->logs, &log_list);
/* finally, initialize the misc device for this log */
ret = misc_register(&log->misc);
if (unlikely(ret)) {
pr_err("failed to register misc device for log '%s'!\n",
log->misc.name);
goto out_free_log;
}
pr_info("created %luK log '%s'\n",
(unsigned long) log->size >> 10, log->misc.name);
return 0;
out_free_log:
kfree(log);
out_free_buffer:
vfree(buffer);
return ret;
}
static int __init logger_init(void)
{
int ret;
ret = create_log(LOGGER_LOG_MAIN, CONFIG_LOGCAT_SIZE*1024);
if (unlikely(ret))
goto out;
ret = create_log(LOGGER_LOG_EVENTS, CONFIG_LOGCAT_SIZE*1024);
if (unlikely(ret))
goto out;
ret = create_log(LOGGER_LOG_RADIO, CONFIG_LOGCAT_SIZE*1024);
if (unlikely(ret))
goto out;
ret = create_log(LOGGER_LOG_SYSTEM, CONFIG_LOGCAT_SIZE*1024);
if (unlikely(ret))
goto out;
out:
return ret;
}
static void __exit logger_exit(void)
{
struct logger_log *current_log, *next_log;
list_for_each_entry_safe(current_log, next_log, &log_list, logs) {
/* we have to delete all the entry inside log_list */
misc_deregister(&current_log->misc);
vfree(current_log->buffer);
kfree(current_log->misc.name);
list_del(&current_log->logs);
kfree(current_log);
}
}
device_initcall(logger_init);
module_exit(logger_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Robert Love, <rlove@google.com>");
MODULE_DESCRIPTION("Android Logger");

View File

@ -1,89 +0,0 @@
/* include/linux/logger.h
*
* Copyright (C) 2007-2008 Google, Inc.
* Author: Robert Love <rlove@android.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _LINUX_LOGGER_H
#define _LINUX_LOGGER_H
#include <linux/types.h>
#include <linux/ioctl.h>
/**
* struct user_logger_entry_compat - defines a single entry that is given to a logger
* @len: The length of the payload
* @__pad: Two bytes of padding that appear to be required
* @pid: The generating process' process ID
* @tid: The generating process' thread ID
* @sec: The number of seconds that have elapsed since the Epoch
* @nsec: The number of nanoseconds that have elapsed since @sec
* @msg: The message that is to be logged
*
* The userspace structure for version 1 of the logger_entry ABI.
* This structure is returned to userspace unless the caller requests
* an upgrade to a newer ABI version.
*/
struct user_logger_entry_compat {
__u16 len;
__u16 __pad;
__s32 pid;
__s32 tid;
__s32 sec;
__s32 nsec;
char msg[0];
};
/**
* struct logger_entry - defines a single entry that is given to a logger
* @len: The length of the payload
* @hdr_size: sizeof(struct logger_entry_v2)
* @pid: The generating process' process ID
* @tid: The generating process' thread ID
* @sec: The number of seconds that have elapsed since the Epoch
* @nsec: The number of nanoseconds that have elapsed since @sec
* @euid: Effective UID of logger
* @msg: The message that is to be logged
*
* The structure for version 2 of the logger_entry ABI.
* This structure is returned to userspace if ioctl(LOGGER_SET_VERSION)
* is called with version >= 2
*/
struct logger_entry {
__u16 len;
__u16 hdr_size;
__s32 pid;
__s32 tid;
__s32 sec;
__s32 nsec;
kuid_t euid;
char msg[0];
};
#define LOGGER_LOG_RADIO "log_radio" /* radio-related messages */
#define LOGGER_LOG_EVENTS "log_events" /* system/hardware events */
#define LOGGER_LOG_SYSTEM "log_system" /* system/framework messages */
#define LOGGER_LOG_MAIN "log_main" /* everything else */
#define LOGGER_ENTRY_MAX_PAYLOAD 4076
#define __LOGGERIO 0xAE
#define LOGGER_GET_LOG_BUF_SIZE _IO(__LOGGERIO, 1) /* size of log */
#define LOGGER_GET_LOG_LEN _IO(__LOGGERIO, 2) /* used log len */
#define LOGGER_GET_NEXT_ENTRY_LEN _IO(__LOGGERIO, 3) /* next entry len */
#define LOGGER_FLUSH_LOG _IO(__LOGGERIO, 4) /* flush log */
#define LOGGER_GET_VERSION _IO(__LOGGERIO, 5) /* abi version */
#define LOGGER_SET_VERSION _IO(__LOGGERIO, 6) /* abi version */
#endif /* _LINUX_LOGGER_H */

View File

@ -1,65 +0,0 @@
/* drivers/staging/android/uapi/android_alarm.h
*
* Copyright (C) 2006-2007 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _UAPI_LINUX_ANDROID_ALARM_H
#define _UAPI_LINUX_ANDROID_ALARM_H
#include <linux/ioctl.h>
#include <linux/time.h>
enum android_alarm_type {
/* return code bit numbers or set alarm arg */
ANDROID_ALARM_RTC_WAKEUP,
ANDROID_ALARM_RTC,
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
ANDROID_ALARM_ELAPSED_REALTIME,
ANDROID_ALARM_RTC_POWEROFF_WAKEUP,
ANDROID_ALARM_SYSTEMTIME,
ANDROID_ALARM_TYPE_COUNT,
/* return code bit numbers */
/* ANDROID_ALARM_TIME_CHANGE = 16 */
};
enum android_alarm_return_flags {
ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP,
ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC,
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK =
1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
ANDROID_ALARM_ELAPSED_REALTIME_MASK =
1U << ANDROID_ALARM_ELAPSED_REALTIME,
ANDROID_ALARM_RTC_POWEROFF_WAKEUP_MASK =
1U << ANDROID_ALARM_RTC_POWEROFF_WAKEUP,
ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME,
ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
};
/* Disable alarm */
#define ANDROID_ALARM_CLEAR(type) _IO('a', 0 | ((type) << 4))
/* Ack last alarm and wait for next */
#define ANDROID_ALARM_WAIT _IO('a', 1)
#define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size)
/* Set alarm */
#define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec)
#define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec)
#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec)
#define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec)
#define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0)))
#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4)
#endif

View File

@ -873,6 +873,9 @@ config USB_G_PRINTER
config USB_G_ANDROID
boolean "Android Composite Gadget"
depends on SND
select SND_PCM
select SND_RAWMIDI
select USB_F_ACM
select USB_F_SERIAL
select USB_LIBCOMPOSITE

View File

@ -191,7 +191,7 @@ static struct usb_gadget_strings *midi_strings[] = {
NULL,
};
static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
static struct usb_request *midi_alloc_ep_req(struct usb_ep *ep, unsigned length)
{
struct usb_request *req;
@ -207,7 +207,7 @@ static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
return req;
}
static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
static void midi_free_ep_req(struct usb_ep *ep, struct usb_request *req)
{
kfree(req->buf);
usb_ep_free_request(ep, req);
@ -278,7 +278,7 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req)
if (ep == midi->out_ep)
f_midi_handle_out_data(ep, req);
free_ep_req(ep, req);
midi_free_ep_req(ep, req);
return;
case -EOVERFLOW: /* buffer overrun on read means that
@ -365,7 +365,7 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* allocate a bunch of read buffers and queue them all at once. */
for (i = 0; i < midi->qlen && err == 0; i++) {
struct usb_request *req =
alloc_ep_req(midi->out_ep, midi->buflen);
midi_alloc_ep_req(midi->out_ep, midi->buflen);
if (req == NULL)
return -ENOMEM;
@ -409,7 +409,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
card = midi->card;
midi->card = NULL;
if (card)
snd_card_free(card);
snd_card_free_when_closed(card);
kfree(midi->id);
midi->id = NULL;
@ -546,10 +546,10 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
return;
if (!req)
req = alloc_ep_req(ep, midi->buflen);
req = midi_alloc_ep_req(ep, midi->buflen);
if (!req) {
ERROR(midi, "gmidi_transmit: alloc_ep_request failed\n");
ERROR(midi, "gmidi_transmit: midi_alloc_ep_request failed\n");
return;
}
req->length = 0;
@ -575,7 +575,7 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
if (req->length > 0)
usb_ep_queue(ep, req, GFP_ATOMIC);
else
free_ep_req(ep, req);
midi_free_ep_req(ep, req);
}
static void f_midi_in_tasklet(unsigned long data)

View File

@ -213,6 +213,7 @@ static int parse_options(struct super_block *sb, char *options)
static int adfs_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_NODIRATIME;
return parse_options(sb, data);
}

View File

@ -549,6 +549,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
pr_debug("AFFS: remount(flags=0x%x,opts=\"%s\")\n",*flags,data);
sync_filesystem(sb);
*flags |= MS_NODIRATIME;
memcpy(volume, sbi->s_volume, 32);

View File

@ -908,6 +908,7 @@ befs_fill_super(struct super_block *sb, void *data, int silent)
static int
befs_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
if (!(*flags & MS_RDONLY))
return -EINVAL;
return 0;

View File

@ -1239,6 +1239,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
unsigned int old_metadata_ratio = fs_info->metadata_ratio;
int ret;
sync_filesystem(sb);
btrfs_remount_prepare(fs_info);
ret = btrfs_parse_options(root, data);

View File

@ -521,6 +521,7 @@ static int cifs_show_stats(struct seq_file *s, struct dentry *root)
static int cifs_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_NODIRATIME;
return 0;
}

View File

@ -391,8 +391,7 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
if (!host_file->f_op)
return -ENOTDIR;
if (host_file->f_op->readdir)
{
if (host_file->f_op->readdir) {
/* potemkin case: we were handed a directory inode.
* We can't use vfs_readdir because we have to keep the file
* position in sync between the coda_file and the host_file.
@ -410,8 +409,20 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
coda_file->f_pos = host_file->f_pos;
mutex_unlock(&host_inode->i_mutex);
}
else /* Venus: we must read Venus dirents from a file */
} else if (host_file->f_op->iterate) {
struct inode *host_inode = file_inode(host_file);
struct dir_context *ctx = buf;
mutex_lock(&host_inode->i_mutex);
ret = -ENOENT;
if (!IS_DEADDIR(host_inode)) {
ret = host_file->f_op->iterate(host_file, ctx);
file_accessed(host_file);
}
mutex_unlock(&host_inode->i_mutex);
coda_file->f_pos = ctx->pos;
} else /* Venus: we must read Venus dirents from a file */
ret = coda_venus_readdir(coda_file, buf, filldir);
return ret;

View File

@ -96,6 +96,7 @@ void coda_destroy_inodecache(void)
static int coda_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_NOATIME;
return 0;
}

View File

@ -832,6 +832,7 @@ struct compat_old_linux_dirent {
};
struct compat_readdir_callback {
struct dir_context ctx;
struct compat_old_linux_dirent __user *dirent;
int result;
};
@ -873,15 +874,15 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
{
int error;
struct fd f = fdget(fd);
struct compat_readdir_callback buf;
struct compat_readdir_callback buf = {
.ctx.actor = compat_fillonedir,
.dirent = dirent
};
if (!f.file)
return -EBADF;
buf.result = 0;
buf.dirent = dirent;
error = vfs_readdir(f.file, compat_fillonedir, &buf);
error = iterate_dir(f.file, &buf.ctx);
if (buf.result)
error = buf.result;
@ -897,6 +898,7 @@ struct compat_linux_dirent {
};
struct compat_getdents_callback {
struct dir_context ctx;
struct compat_linux_dirent __user *current_dir;
struct compat_linux_dirent __user *previous;
int count;
@ -951,7 +953,11 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
{
struct fd f;
struct compat_linux_dirent __user * lastdirent;
struct compat_getdents_callback buf;
struct compat_getdents_callback buf = {
.ctx.actor = compat_filldir,
.current_dir = dirent,
.count = count
};
int error;
if (!access_ok(VERIFY_WRITE, dirent, count))
@ -961,17 +967,12 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
if (!f.file)
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
error = vfs_readdir(f.file, compat_filldir, &buf);
error = iterate_dir(f.file, &buf.ctx);
if (error >= 0)
error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
if (put_user(f.file->f_pos, &lastdirent->d_off))
if (put_user(buf.ctx.pos, &lastdirent->d_off))
error = -EFAULT;
else
error = count - buf.count;
@ -983,6 +984,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
#ifdef __ARCH_WANT_COMPAT_SYS_GETDENTS64
struct compat_getdents_callback64 {
struct dir_context ctx;
struct linux_dirent64 __user *current_dir;
struct linux_dirent64 __user *previous;
int count;
@ -1036,7 +1038,11 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
{
struct fd f;
struct linux_dirent64 __user * lastdirent;
struct compat_getdents_callback64 buf;
struct compat_getdents_callback64 buf = {
.ctx.actor = compat_filldir64,
.current_dir = dirent,
.count = count
};
int error;
if (!access_ok(VERIFY_WRITE, dirent, count))
@ -1046,17 +1052,12 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
if (!f.file)
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
error = vfs_readdir(f.file, compat_filldir64, &buf);
error = iterate_dir(f.file, &buf.ctx);
if (error >= 0)
error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
typeof(lastdirent->d_off) d_off = f.file->f_pos;
typeof(lastdirent->d_off) d_off = buf.ctx.pos;
if (__put_user_unaligned(d_off, &lastdirent->d_off))
error = -EFAULT;
else

View File

@ -227,6 +227,7 @@ static void cramfs_put_super(struct super_block *sb)
static int cramfs_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_RDONLY;
return 0;
}

View File

@ -218,6 +218,7 @@ static int debugfs_remount(struct super_block *sb, int *flags, char *data)
int err;
struct debugfs_fs_info *fsi = sb->s_fs_info;
sync_filesystem(sb);
err = debugfs_parse_options(data, &fsi->mount_opts);
if (err)
goto fail;

View File

@ -313,6 +313,7 @@ static int devpts_remount(struct super_block *sb, int *flags, char *data)
struct pts_fs_info *fsi = DEVPTS_SB(sb);
struct pts_mount_opts *opts = &fsi->mount_opts;
sync_filesystem(sb);
err = parse_mount_options(data, PARSE_REMOUNT, opts);
/*

View File

@ -68,6 +68,7 @@ static ssize_t ecryptfs_read_update_atime(struct kiocb *iocb,
}
struct ecryptfs_getdents_callback {
struct dir_context ctx;
void *dirent;
struct dentry *dentry;
filldir_t filldir;
@ -115,18 +116,19 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir)
int rc;
struct file *lower_file;
struct inode *inode;
struct ecryptfs_getdents_callback buf;
struct ecryptfs_getdents_callback buf = {
.dirent = dirent,
.dentry = file->f_path.dentry,
.filldir = filldir,
.filldir_called = 0,
.entries_written = 0,
.ctx.actor = ecryptfs_filldir
};
lower_file = ecryptfs_file_to_lower(file);
lower_file->f_pos = file->f_pos;
inode = file_inode(file);
memset(&buf, 0, sizeof(buf));
buf.dirent = dirent;
buf.dentry = file->f_path.dentry;
buf.filldir = filldir;
buf.filldir_called = 0;
buf.entries_written = 0;
rc = vfs_readdir(lower_file, ecryptfs_filldir, (void *)&buf);
rc = iterate_dir(lower_file, &buf.ctx);
file->f_pos = lower_file->f_pos;
if (rc < 0)
goto out;

View File

@ -113,6 +113,7 @@ static void efs_put_super(struct super_block *s)
static int efs_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_RDONLY;
return 0;
}

View File

@ -212,6 +212,7 @@ reconnect_path(struct vfsmount *mnt, struct dentry *target_dir, char *nbuf)
}
struct getdents_callback {
struct dir_context ctx;
char *name; /* name that was found. It already points to a
buffer NAME_MAX+1 is size */
unsigned long ino; /* the inum we are looking for */
@ -254,7 +255,11 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
struct inode *dir = path->dentry->d_inode;
int error;
struct file *file;
struct getdents_callback buffer;
struct getdents_callback buffer = {
.ctx.actor = filldir_one,
.name = name,
.ino = child->d_inode->i_ino
};
error = -ENOTDIR;
if (!dir || !S_ISDIR(dir->i_mode))
@ -271,17 +276,14 @@ static int get_name(const struct path *path, char *name, struct dentry *child)
goto out;
error = -EINVAL;
if (!file->f_op->readdir)
if (!file->f_op->readdir && !file->f_op->iterate)
goto out_close;
buffer.name = name;
buffer.ino = child->d_inode->i_ino;
buffer.found = 0;
buffer.sequence = 0;
while (1) {
int old_seq = buffer.sequence;
error = vfs_readdir(file, filldir_one, &buffer);
error = iterate_dir(file, &buffer.ctx);
if (buffer.found) {
error = 0;
break;

View File

@ -1254,6 +1254,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
unsigned long old_sb_flags;
int err;
sync_filesystem(sb);
spin_lock(&sbi->s_lock);
/* Store the old options */

View File

@ -2588,6 +2588,8 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data)
int i;
#endif
sync_filesystem(sb);
/* Store the original options */
old_sb_flags = sb->s_flags;
old_opts.s_mount_opt = sbi->s_mount_opt;

View File

@ -4624,6 +4624,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
#endif
char *orig_data = kstrdup(data, GFP_KERNEL);
sync_filesystem(sb);
/* Store the original options */
old_sb_flags = sb->s_flags;
old_opts.s_mount_opt = sbi->s_mount_opt;

View File

@ -239,7 +239,6 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
if (test_opt(sbi, DISABLE_EXT_IDENTIFY))
seq_puts(seq, ",disable_ext_identify");
seq_printf(seq, ",active_logs=%u", sbi->active_logs);
return 0;
}

View File

@ -632,6 +632,8 @@ static int fat_remount(struct super_block *sb, int *flags, char *data)
struct msdos_sb_info *sbi = MSDOS_SB(sb);
*flags |= MS_NODIRATIME | (sbi->options.isvfat ? 0 : MS_NOATIME);
sync_filesystem(sb);
/* make sure we update state on remount. */
new_rdonly = *flags & MS_RDONLY;
if (new_rdonly != (sb->s_flags & MS_RDONLY)) {

View File

@ -124,6 +124,7 @@ vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp)
static int vxfs_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_RDONLY;
return 0;
}

View File

@ -45,6 +45,7 @@ struct wb_writeback_work {
unsigned int for_kupdate:1;
unsigned int range_cyclic:1;
unsigned int for_background:1;
unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */
enum wb_reason reason; /* why was writeback initiated? */
struct list_head list; /* pending work list */
@ -456,9 +457,11 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
/*
* Make sure to wait on the data before writing out the metadata.
* This is important for filesystems that modify metadata on data
* I/O completion.
* I/O completion. We don't do it for sync(2) writeback because it has a
* separate, external IO completion path and ->sync_fs for guaranteeing
* inode metadata is written back correctly.
*/
if (wbc->sync_mode == WB_SYNC_ALL) {
if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync) {
int err = filemap_fdatawait(mapping);
if (ret == 0)
ret = err;
@ -610,6 +613,7 @@ static long writeback_sb_inodes(struct super_block *sb,
.tagged_writepages = work->tagged_writepages,
.for_kupdate = work->for_kupdate,
.for_background = work->for_background,
.for_sync = work->for_sync,
.range_cyclic = work->range_cyclic,
.range_start = 0,
.range_end = LLONG_MAX,
@ -1393,6 +1397,7 @@ void sync_inodes_sb(struct super_block *sb)
.range_cyclic = 0,
.done = &done,
.reason = WB_REASON_SYNC,
.for_sync = 1,
};
/* Nothing to do? */

View File

@ -135,6 +135,7 @@ static void fuse_evict_inode(struct inode *inode)
static int fuse_remount_fs(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
if (*flags & MS_MANDLOCK)
return -EINVAL;

View File

@ -88,7 +88,10 @@ static int gfs2_get_name(struct dentry *parent, char *name,
struct inode *dir = parent->d_inode;
struct inode *inode = child->d_inode;
struct gfs2_inode *dip, *ip;
struct get_name_filldir gnfd;
struct get_name_filldir gnfd = {
.ctx.actor = get_name_filldir,
.name = name
};
struct gfs2_holder gh;
u64 offset = 0;
int error;
@ -106,7 +109,6 @@ static int gfs2_get_name(struct dentry *parent, char *name,
*name = 0;
gnfd.inum.no_addr = ip->i_no_addr;
gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
gnfd.name = name;
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
if (error)

View File

@ -1142,6 +1142,8 @@ static int gfs2_remount_fs(struct super_block *sb, int *flags, char *data)
struct gfs2_tune *gt = &sdp->sd_tune;
int error;
sync_filesystem(sb);
spin_lock(&gt->gt_spin);
args.ar_commit = gt->gt_logd_secs;
args.ar_quota_quantum = gt->gt_quota_quantum;

View File

@ -112,6 +112,7 @@ static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf)
static int hfs_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_NODIRATIME;
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;

View File

@ -323,6 +323,7 @@ static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf)
static int hfsplus_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
if (!(*flags & MS_RDONLY)) {

View File

@ -395,6 +395,8 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
struct hpfs_sb_info *sbi = hpfs_sb(s);
char *new_opts = kstrdup(data, GFP_KERNEL);
sync_filesystem(s);
*flags |= MS_NOATIME;
hpfs_lock(s);

View File

@ -979,6 +979,41 @@ void unlock_new_inode(struct inode *inode)
}
EXPORT_SYMBOL(unlock_new_inode);
/**
* lock_two_nondirectories - take two i_mutexes on non-directory objects
*
* Lock any non-NULL argument that is not a directory.
* Zero, one or two objects may be locked by this function.
*
* @inode1: first inode to lock
* @inode2: second inode to lock
*/
void lock_two_nondirectories(struct inode *inode1, struct inode *inode2)
{
if (inode1 > inode2)
swap(inode1, inode2);
if (inode1 && !S_ISDIR(inode1->i_mode))
mutex_lock(&inode1->i_mutex);
if (inode2 && !S_ISDIR(inode2->i_mode) && inode2 != inode1)
mutex_lock_nested(&inode2->i_mutex, I_MUTEX_NONDIR2);
}
EXPORT_SYMBOL(lock_two_nondirectories);
/**
* unlock_two_nondirectories - release locks from lock_two_nondirectories()
* @inode1: first inode to unlock
* @inode2: second inode to unlock
*/
void unlock_two_nondirectories(struct inode *inode1, struct inode *inode2)
{
if (inode1 && !S_ISDIR(inode1->i_mode))
mutex_unlock(&inode1->i_mutex);
if (inode2 && !S_ISDIR(inode2->i_mode) && inode2 != inode1)
mutex_unlock(&inode2->i_mutex);
}
EXPORT_SYMBOL(unlock_two_nondirectories);
/**
* iget5_locked - obtain an inode from a mounted file system
* @sb: super block of file system

View File

@ -243,6 +243,7 @@ static int jffs2_remount_fs(struct super_block *sb, int *flags, char *data)
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
int err;
sync_filesystem(sb);
err = jffs2_parse_options(c, data);
if (err)
return -EINVAL;

View File

@ -413,6 +413,7 @@ static int jfs_remount(struct super_block *sb, int *flags, char *data)
int flag = JFS_SBI(sb)->flag;
int ret;
sync_filesystem(sb);
if (!parse_options(data, sb, &newLVSize, &flag)) {
return -EINVAL;
}

View File

@ -123,6 +123,7 @@ static int minix_remount (struct super_block * sb, int * flags, char * data)
struct minix_sb_info * sbi = minix_sb(sb);
struct minix_super_block * ms;
sync_filesystem(sb);
ms = sbi->s_ms;
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;

View File

@ -99,6 +99,7 @@ static void destroy_inodecache(void)
static int ncp_remount(struct super_block *sb, int *flags, char* data)
{
sync_filesystem(sb);
*flags |= MS_NODIRATIME;
return 0;
}

View File

@ -2133,6 +2133,8 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
struct nfs4_mount_data *options4 = (struct nfs4_mount_data *)raw_data;
u32 nfsvers = nfss->nfs_client->rpc_ops->version;
sync_filesystem(sb);
/*
* Userspace mount programs that send binary options generally send
* them populated with default values. We have no way to know which

View File

@ -240,11 +240,16 @@ struct name_list {
struct list_head list;
};
struct nfs4_dir_ctx {
struct dir_context ctx;
struct list_head names;
};
static int
nfsd4_build_namelist(void *arg, const char *name, int namlen,
loff_t offset, u64 ino, unsigned int d_type)
{
struct list_head *names = arg;
struct nfs4_dir_ctx *ctx = arg;
struct name_list *entry;
if (namlen != HEXDIR_LEN - 1)
@ -254,7 +259,7 @@ nfsd4_build_namelist(void *arg, const char *name, int namlen,
return -ENOMEM;
memcpy(entry->name, name, HEXDIR_LEN - 1);
entry->name[HEXDIR_LEN - 1] = '\0';
list_add(&entry->list, names);
list_add(&entry->list, &ctx->names);
return 0;
}
@ -263,7 +268,10 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
{
const struct cred *original_cred;
struct dentry *dir = nn->rec_file->f_path.dentry;
LIST_HEAD(names);
struct nfs4_dir_ctx ctx = {
.ctx.actor = nfsd4_build_namelist,
.names = LIST_HEAD_INIT(ctx.names)
};
int status;
status = nfs4_save_creds(&original_cred);
@ -276,11 +284,11 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
return status;
}
status = vfs_readdir(nn->rec_file, nfsd4_build_namelist, &names);
status = iterate_dir(nn->rec_file, &ctx.ctx);
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
while (!list_empty(&names)) {
while (!list_empty(&ctx.names)) {
struct name_list *entry;
entry = list_entry(names.next, struct name_list, list);
entry = list_entry(ctx.names.next, struct name_list, list);
if (!status) {
struct dentry *dentry;
dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);

View File

@ -1950,6 +1950,7 @@ struct buffered_dirent {
};
struct readdir_data {
struct dir_context ctx;
char *dirent;
size_t used;
int full;
@ -1981,13 +1982,15 @@ static int nfsd_buffered_filldir(void *__buf, const char *name, int namlen,
static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func,
struct readdir_cd *cdp, loff_t *offsetp)
{
struct readdir_data buf;
struct buffered_dirent *de;
int host_err;
int size;
loff_t offset;
struct readdir_data buf = {
.ctx.actor = nfsd_buffered_filldir,
.dirent = (void *)__get_free_page(GFP_KERNEL)
};
buf.dirent = (void *)__get_free_page(GFP_KERNEL);
if (!buf.dirent)
return nfserrno(-ENOMEM);
@ -2001,7 +2004,7 @@ static __be32 nfsd_buffered_readdir(struct file *file, filldir_t func,
buf.used = 0;
buf.full = 0;
host_err = vfs_readdir(file, nfsd_buffered_filldir, &buf);
host_err = iterate_dir(file, &buf.ctx);
if (buf.full)
host_err = 0;

View File

@ -1114,6 +1114,7 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
unsigned long old_mount_opt;
int err;
sync_filesystem(sb);
old_sb_flags = sb->s_flags;
old_mount_opt = nilfs->ns_mount_opt;

View File

@ -468,6 +468,8 @@ static int ntfs_remount(struct super_block *sb, int *flags, char *opt)
ntfs_debug("Entering with remount options string: %s", opt);
sync_filesystem(sb);
#ifndef NTFS_RW
/* For read-only compiled driver, enforce read-only flag. */
*flags |= MS_RDONLY;

View File

@ -632,6 +632,8 @@ static int ocfs2_remount(struct super_block *sb, int *flags, char *data)
struct ocfs2_super *osb = OCFS2_SB(sb);
u32 tmp;
sync_filesystem(sb);
if (!ocfs2_parse_options(sb, data, &parsed_options, 1) ||
!ocfs2_check_set_options(sb, &parsed_options)) {
ret = -EINVAL;

View File

@ -375,6 +375,7 @@ static struct inode *openprom_iget(struct super_block *sb, ino_t ino)
static int openprom_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_NOATIME;
return 0;
}

View File

@ -140,12 +140,6 @@ struct pid_entry {
NULL, &proc_single_file_operations, \
{ .proc_show = show } )
/* ANDROID is for special files in /proc. */
#define ANDROID(NAME, MODE, OTYPE) \
NOD(NAME, (S_IFREG|(MODE)), \
&proc_##OTYPE##_inode_operations, \
&proc_##OTYPE##_operations, {})
/*
* Count the number of hardlinks for the pid_entry table, excluding the .
* and .. links.
@ -1015,35 +1009,6 @@ out:
return err < 0 ? err : count;
}
static int oom_adjust_permission(struct inode *inode, int mask)
{
uid_t uid;
struct task_struct *p;
p = get_proc_task(inode);
if(p) {
uid = task_uid(p);
put_task_struct(p);
}
/*
* System Server (uid == 1000) is granted access to oom_adj of all
* android applications (uid > 10000) as and services (uid >= 1000)
*/
if (p && (current_fsuid() == 1000) && (uid >= 1000)) {
if (inode->i_mode >> 6 & mask) {
return 0;
}
}
/* Fall back to default. */
return generic_permission(inode, mask);
}
static const struct inode_operations proc_oom_adj_inode_operations = {
.permission = oom_adjust_permission,
};
static const struct file_operations proc_oom_adj_operations = {
.read = oom_adj_read,
.write = oom_adj_write,
@ -2941,8 +2906,8 @@ static const struct pid_entry tgid_base_stuff[] = {
REG("cgroup", S_IRUGO, proc_cgroup_operations),
#endif
INF("oom_score", S_IRUGO, proc_oom_score),
ANDROID("oom_adj", S_IRUGO|S_IWUSR, oom_adj),
REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
REG("oom_adj", S_IRUSR, proc_oom_adj_operations),
REG("oom_score_adj", S_IRUSR, proc_oom_score_adj_operations),
#ifdef CONFIG_AUDITSYSCALL
REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations),
REG("sessionid", S_IRUGO, proc_sessionid_operations),
@ -3298,8 +3263,8 @@ static const struct pid_entry tid_base_stuff[] = {
REG("cgroup", S_IRUGO, proc_cgroup_operations),
#endif
INF("oom_score", S_IRUGO, proc_oom_score),
REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adj_operations),
REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
REG("oom_adj", S_IRUSR, proc_oom_adj_operations),
REG("oom_score_adj", S_IRUSR, proc_oom_score_adj_operations),
#ifdef CONFIG_AUDITSYSCALL
REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations),
REG("sessionid", S_IRUGO, proc_sessionid_operations),

View File

@ -92,6 +92,8 @@ static int proc_parse_options(char *options, struct pid_namespace *pid)
int proc_remount(struct super_block *sb, int *flags, char *data)
{
struct pid_namespace *pid = sb->s_fs_info;
sync_filesystem(sb);
return !proc_parse_options(data, pid);
}

View File

@ -778,6 +778,7 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
#define CLEAR_REFS_ALL 1
#define CLEAR_REFS_ANON 2
#define CLEAR_REFS_MAPPED 3
#define CLEAR_REFS_MM_HIWATER_RSS 5
static ssize_t clear_refs_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
@ -797,7 +798,8 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
rv = kstrtoint(strstrip(buffer), 10, &type);
if (rv < 0)
return rv;
if (type < CLEAR_REFS_ALL || type > CLEAR_REFS_MAPPED)
if ((type < CLEAR_REFS_ALL || type > CLEAR_REFS_MAPPED) &&
type != CLEAR_REFS_MM_HIWATER_RSS)
return -EINVAL;
task = get_proc_task(file_inode(file));
if (!task)
@ -808,6 +810,18 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
.pmd_entry = clear_refs_pte_range,
.mm = mm,
};
if (type == CLEAR_REFS_MM_HIWATER_RSS) {
/*
* Writing 5 to /proc/pid/clear_refs resets the peak
* resident set size to this mm's current rss value.
*/
down_write(&mm->mmap_sem);
reset_mm_hiwater_rss(mm);
up_write(&mm->mmap_sem);
goto out_mm;
}
down_read(&mm->mmap_sem);
for (vma = mm->mmap; vma; vma = vma->vm_next) {
clear_refs_walk.private = vma;
@ -831,6 +845,7 @@ static ssize_t clear_refs_write(struct file *file, const char __user *buf,
}
flush_tlb_mm(mm);
up_read(&mm->mmap_sem);
out_mm:
mmput(mm);
}
put_task_struct(task);

View File

@ -249,6 +249,7 @@ static void parse_options(char *options)
static int pstore_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
parse_options(data);
return 0;

View File

@ -46,6 +46,7 @@ static int qnx4_remount(struct super_block *sb, int *flags, char *data)
{
struct qnx4_sb_info *qs;
sync_filesystem(sb);
qs = qnx4_sb(sb);
qs->Version = QNX4_VERSION;
*flags |= MS_RDONLY;

View File

@ -55,6 +55,7 @@ static int qnx6_show_options(struct seq_file *seq, struct dentry *root)
static int qnx6_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_RDONLY;
return 0;
}

View File

@ -20,11 +20,11 @@
#include <asm/uaccess.h>
int vfs_readdir(struct file *file, filldir_t filler, void *buf)
int iterate_dir(struct file *file, struct dir_context *ctx)
{
struct inode *inode = file_inode(file);
int res = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
if (!file->f_op || (!file->f_op->readdir && !file->f_op->iterate))
goto out;
res = security_file_permission(file, MAY_READ);
@ -37,15 +37,21 @@ int vfs_readdir(struct file *file, filldir_t filler, void *buf)
res = -ENOENT;
if (!IS_DEADDIR(inode)) {
res = file->f_op->readdir(file, buf, filler);
if (file->f_op->iterate) {
ctx->pos = file->f_pos;
res = file->f_op->iterate(file, ctx);
file->f_pos = ctx->pos;
} else {
res = file->f_op->readdir(file, ctx, ctx->actor);
ctx->pos = file->f_pos;
}
file_accessed(file);
}
mutex_unlock(&inode->i_mutex);
out:
return res;
}
EXPORT_SYMBOL(vfs_readdir);
EXPORT_SYMBOL(iterate_dir);
/*
* Traditional linux readdir() handling..
@ -66,6 +72,7 @@ struct old_linux_dirent {
};
struct readdir_callback {
struct dir_context ctx;
struct old_linux_dirent __user * dirent;
int result;
};
@ -73,7 +80,7 @@ struct readdir_callback {
static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset,
u64 ino, unsigned int d_type)
{
struct readdir_callback * buf = (struct readdir_callback *) __buf;
struct readdir_callback *buf = (struct readdir_callback *) __buf;
struct old_linux_dirent __user * dirent;
unsigned long d_ino;
@ -107,15 +114,15 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
{
int error;
struct fd f = fdget(fd);
struct readdir_callback buf;
struct readdir_callback buf = {
.ctx.actor = fillonedir,
.dirent = dirent
};
if (!f.file)
return -EBADF;
buf.result = 0;
buf.dirent = dirent;
error = vfs_readdir(f.file, fillonedir, &buf);
error = iterate_dir(f.file, &buf.ctx);
if (buf.result)
error = buf.result;
@ -137,6 +144,7 @@ struct linux_dirent {
};
struct getdents_callback {
struct dir_context ctx;
struct linux_dirent __user * current_dir;
struct linux_dirent __user * previous;
int count;
@ -191,7 +199,11 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
{
struct fd f;
struct linux_dirent __user * lastdirent;
struct getdents_callback buf;
struct getdents_callback buf = {
.ctx.actor = filldir,
.count = count,
.current_dir = dirent
};
int error;
if (!access_ok(VERIFY_WRITE, dirent, count))
@ -201,17 +213,12 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
if (!f.file)
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
error = vfs_readdir(f.file, filldir, &buf);
error = iterate_dir(f.file, &buf.ctx);
if (error >= 0)
error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
if (put_user(f.file->f_pos, &lastdirent->d_off))
if (put_user(buf.ctx.pos, &lastdirent->d_off))
error = -EFAULT;
else
error = count - buf.count;
@ -221,6 +228,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
}
struct getdents_callback64 {
struct dir_context ctx;
struct linux_dirent64 __user * current_dir;
struct linux_dirent64 __user * previous;
int count;
@ -271,7 +279,11 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
{
struct fd f;
struct linux_dirent64 __user * lastdirent;
struct getdents_callback64 buf;
struct getdents_callback64 buf = {
.ctx.actor = filldir64,
.count = count,
.current_dir = dirent
};
int error;
if (!access_ok(VERIFY_WRITE, dirent, count))
@ -281,17 +293,12 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
if (!f.file)
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
buf.count = count;
buf.error = 0;
error = vfs_readdir(f.file, filldir64, &buf);
error = iterate_dir(f.file, &buf.ctx);
if (error >= 0)
error = buf.error;
lastdirent = buf.previous;
if (lastdirent) {
typeof(lastdirent->d_off) d_off = f.file->f_pos;
typeof(lastdirent->d_off) d_off = buf.ctx.pos;
if (__put_user(d_off, &lastdirent->d_off))
error = -EFAULT;
else

View File

@ -1317,6 +1317,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
int i;
#endif
sync_filesystem(s);
reiserfs_write_lock(s);
#ifdef CONFIG_QUOTA

View File

@ -435,6 +435,7 @@ static int romfs_statfs(struct dentry *dentry, struct kstatfs *buf)
*/
static int romfs_remount(struct super_block *sb, int *flags, char *data)
{
sync_filesystem(sb);
*flags |= MS_RDONLY;
return 0;
}

View File

@ -25,6 +25,78 @@ config SQUASHFS
If unsure, say N.
choice
prompt "File decompression options"
depends on SQUASHFS
help
Squashfs now supports two options for decompressing file
data. Traditionally Squashfs has decompressed into an
intermediate buffer and then memcopied it into the page cache.
Squashfs now supports the ability to decompress directly into
the page cache.
If unsure, select "Decompress file data into an intermediate buffer"
config SQUASHFS_FILE_CACHE
bool "Decompress file data into an intermediate buffer"
help
Decompress file data into an intermediate buffer and then
memcopy it into the page cache.
config SQUASHFS_FILE_DIRECT
bool "Decompress files directly into the page cache"
help
Directly decompress file data into the page cache.
Doing so can significantly improve performance because
it eliminates a memcpy and it also removes the lock contention
on the single buffer.
endchoice
choice
prompt "Decompressor parallelisation options"
depends on SQUASHFS
help
Squashfs now supports three parallelisation options for
decompression. Each one exhibits various trade-offs between
decompression performance and CPU and memory usage.
If in doubt, select "Single threaded compression"
config SQUASHFS_DECOMP_SINGLE
bool "Single threaded compression"
help
Traditionally Squashfs has used single-threaded decompression.
Only one block (data or metadata) can be decompressed at any
one time. This limits CPU and memory usage to a minimum.
config SQUASHFS_DECOMP_MULTI
bool "Use multiple decompressors for parallel I/O"
help
By default Squashfs uses a single decompressor but it gives
poor performance on parallel I/O workloads when using multiple CPU
machines due to waiting on decompressor availability.
If you have a parallel I/O workload and your system has enough memory,
using this option may improve overall I/O performance.
This decompressor implementation uses up to two parallel
decompressors per core. It dynamically allocates decompressors
on a demand basis.
config SQUASHFS_DECOMP_MULTI_PERCPU
bool "Use percpu multiple decompressors for parallel I/O"
help
By default Squashfs uses a single decompressor but it gives
poor performance on parallel I/O workloads when using multiple CPU
machines due to waiting on decompressor availability.
This decompressor implementation uses a maximum of one
decompressor per core. It uses percpu variables to ensure
decompression is load-balanced across the cores.
endchoice
config SQUASHFS_XATTR
bool "Squashfs XATTR support"
depends on SQUASHFS
@ -48,6 +120,21 @@ config SQUASHFS_ZLIB
If unsure, say Y.
config SQUASHFS_LZ4
bool "Include support for LZ4 compressed file systems"
depends on SQUASHFS
select LZ4_DECOMPRESS
help
Saying Y here includes support for reading Squashfs file systems
compressed with LZ4 compression. LZ4 compression is mainly
aimed at embedded systems with slower CPUs where the overheads
of zlib are too high.
LZ4 is not the standard compression used in Squashfs and so most
file systems will be readable without selecting this option.
If unsure, say N.
config SQUASHFS_LZO
bool "Include support for LZO compressed file systems"
depends on SQUASHFS

View File

@ -5,7 +5,13 @@
obj-$(CONFIG_SQUASHFS) += squashfs.o
squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
squashfs-y += namei.o super.o symlink.o decompressor.o
squashfs-$(CONFIG_SQUASHFS_FILE_CACHE) += file_cache.o
squashfs-$(CONFIG_SQUASHFS_FILE_DIRECT) += file_direct.o page_actor.o
squashfs-$(CONFIG_SQUASHFS_DECOMP_SINGLE) += decompressor_single.o
squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI) += decompressor_multi.o
squashfs-$(CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU) += decompressor_multi_percpu.o
squashfs-$(CONFIG_SQUASHFS_XATTR) += xattr.o xattr_id.o
squashfs-$(CONFIG_SQUASHFS_LZ4) += lz4_wrapper.o
squashfs-$(CONFIG_SQUASHFS_LZO) += lzo_wrapper.o
squashfs-$(CONFIG_SQUASHFS_XZ) += xz_wrapper.o
squashfs-$(CONFIG_SQUASHFS_ZLIB) += zlib_wrapper.o

View File

@ -36,6 +36,7 @@
#include "squashfs_fs_sb.h"
#include "squashfs.h"
#include "decompressor.h"
#include "page_actor.h"
/*
* Read the metadata block length, this is stored in the first two
@ -86,16 +87,16 @@ static struct buffer_head *get_block_length(struct super_block *sb,
* generated a larger block - this does occasionally happen with compression
* algorithms).
*/
int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
int length, u64 *next_index, int srclength, int pages)
int squashfs_read_data(struct super_block *sb, u64 index, int length,
u64 *next_index, struct squashfs_page_actor *output)
{
struct squashfs_sb_info *msblk = sb->s_fs_info;
struct buffer_head **bh;
int offset = index & ((1 << msblk->devblksize_log2) - 1);
u64 cur_index = index >> msblk->devblksize_log2;
int bytes, compressed, b = 0, k = 0, page = 0, avail;
int bytes, compressed, b = 0, k = 0, avail, i;
bh = kcalloc(((srclength + msblk->devblksize - 1)
bh = kcalloc(((output->length + msblk->devblksize - 1)
>> msblk->devblksize_log2) + 1, sizeof(*bh), GFP_KERNEL);
if (bh == NULL)
return -ENOMEM;
@ -111,9 +112,9 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
*next_index = index + length;
TRACE("Block @ 0x%llx, %scompressed size %d, src size %d\n",
index, compressed ? "" : "un", length, srclength);
index, compressed ? "" : "un", length, output->length);
if (length < 0 || length > srclength ||
if (length < 0 || length > output->length ||
(index + length) > msblk->bytes_used)
goto read_failure;
@ -145,7 +146,7 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
TRACE("Block @ 0x%llx, %scompressed size %d\n", index,
compressed ? "" : "un", length);
if (length < 0 || length > srclength ||
if (length < 0 || length > output->length ||
(index + length) > msblk->bytes_used)
goto block_release;
@ -158,35 +159,36 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
ll_rw_block(READ, b - 1, bh + 1);
}
for (i = 0; i < b; i++) {
wait_on_buffer(bh[i]);
if (!buffer_uptodate(bh[i]))
goto block_release;
}
if (compressed) {
length = squashfs_decompress(msblk, buffer, bh, b, offset,
length, srclength, pages);
length = squashfs_decompress(msblk, bh, b, offset, length,
output);
if (length < 0)
goto read_failure;
} else {
/*
* Block is uncompressed.
*/
int i, in, pg_offset = 0;
for (i = 0; i < b; i++) {
wait_on_buffer(bh[i]);
if (!buffer_uptodate(bh[i]))
goto block_release;
}
int in, pg_offset = 0;
void *data = squashfs_first_page(output);
for (bytes = length; k < b; k++) {
in = min(bytes, msblk->devblksize - offset);
bytes -= in;
while (in) {
if (pg_offset == PAGE_CACHE_SIZE) {
page++;
data = squashfs_next_page(output);
pg_offset = 0;
}
avail = min_t(int, in, PAGE_CACHE_SIZE -
pg_offset);
memcpy(buffer[page] + pg_offset,
bh[k]->b_data + offset, avail);
memcpy(data + pg_offset, bh[k]->b_data + offset,
avail);
in -= avail;
pg_offset += avail;
offset += avail;
@ -194,6 +196,7 @@ int squashfs_read_data(struct super_block *sb, void **buffer, u64 index,
offset = 0;
put_bh(bh[k]);
}
squashfs_finish_page(output);
}
kfree(bh);

Some files were not shown because too many files have changed in this diff Show More