Merge ebd326ce72 ("Merge tag 'locking-core-2022-03-21' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip") into android-mainline
Steps on the way to 5.18-rc1 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I226a6ed299a2c600b0652b2a9efc9ae2f4caf7d9
This commit is contained in:
@@ -55,8 +55,9 @@ Description: Controls the in-place-update policy.
|
||||
0x04 F2FS_IPU_UTIL
|
||||
0x08 F2FS_IPU_SSR_UTIL
|
||||
0x10 F2FS_IPU_FSYNC
|
||||
0x20 F2FS_IPU_ASYNC,
|
||||
0x20 F2FS_IPU_ASYNC
|
||||
0x40 F2FS_IPU_NOCACHE
|
||||
0x80 F2FS_IPU_HONOR_OPU_WRITE
|
||||
==== =================
|
||||
|
||||
Refer segment.h for details.
|
||||
@@ -98,6 +99,33 @@ Description: Controls the issue rate of discard commands that consist of small
|
||||
checkpoint is triggered, and issued during the checkpoint.
|
||||
By default, it is disabled with 0.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/max_discard_request
|
||||
Date: December 2021
|
||||
Contact: "Konstantin Vyshetsky" <vkon@google.com>
|
||||
Description: Controls the number of discards a thread will issue at a time.
|
||||
Higher number will allow the discard thread to finish its work
|
||||
faster, at the cost of higher latency for incomming I/O.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/min_discard_issue_time
|
||||
Date: December 2021
|
||||
Contact: "Konstantin Vyshetsky" <vkon@google.com>
|
||||
Description: Controls the interval the discard thread will wait between
|
||||
issuing discard requests when there are discards to be issued and
|
||||
no I/O aware interruptions occur.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/mid_discard_issue_time
|
||||
Date: December 2021
|
||||
Contact: "Konstantin Vyshetsky" <vkon@google.com>
|
||||
Description: Controls the interval the discard thread will wait between
|
||||
issuing discard requests when there are discards to be issued and
|
||||
an I/O aware interruption occurs.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/max_discard_issue_time
|
||||
Date: December 2021
|
||||
Contact: "Konstantin Vyshetsky" <vkon@google.com>
|
||||
Description: Controls the interval the discard thread will wait when there are
|
||||
no discard operations to be issued.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/discard_granularity
|
||||
Date: July 2017
|
||||
Contact: "Chao Yu" <yuchao0@huawei.com>
|
||||
@@ -269,11 +297,16 @@ Description: Shows current reserved blocks in system, it may be temporarily
|
||||
What: /sys/fs/f2fs/<disk>/gc_urgent
|
||||
Date: August 2017
|
||||
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
|
||||
Description: Do background GC aggressively when set. When gc_urgent = 1,
|
||||
background thread starts to do GC by given gc_urgent_sleep_time
|
||||
interval. When gc_urgent = 2, F2FS will lower the bar of
|
||||
checking idle in order to process outstanding discard commands
|
||||
and GC a little bit aggressively. It is set to 0 by default.
|
||||
Description: Do background GC aggressively when set. Set to 0 by default.
|
||||
gc urgent high(1): does GC forcibly in a period of given
|
||||
gc_urgent_sleep_time and ignores I/O idling check. uses greedy
|
||||
GC approach and turns SSR mode on.
|
||||
gc urgent low(2): lowers the bar of checking I/O idling in
|
||||
order to process outstanding discard commands and GC a
|
||||
little bit aggressively. uses cost benefit GC approach.
|
||||
gc urgent mid(3): does GC forcibly in a period of given
|
||||
gc_urgent_sleep_time and executes a mid level of I/O idling check.
|
||||
uses cost benefit GC approach.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/gc_urgent_sleep_time
|
||||
Date: August 2017
|
||||
@@ -430,6 +463,7 @@ Description: Show status of f2fs superblock in real time.
|
||||
0x800 SBI_QUOTA_SKIP_FLUSH skip flushing quota in current CP
|
||||
0x1000 SBI_QUOTA_NEED_REPAIR quota file may be corrupted
|
||||
0x2000 SBI_IS_RESIZEFS resizefs is in process
|
||||
0x4000 SBI_IS_FREEZING freefs is in process
|
||||
====== ===================== =================================
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/ckpt_thread_ioprio
|
||||
@@ -503,7 +537,7 @@ Date: July 2021
|
||||
Contact: "Daeho Jeong" <daehojeong@google.com>
|
||||
Description: Show how many segments have been reclaimed by GC during a specific
|
||||
GC mode (0: GC normal, 1: GC idle CB, 2: GC idle greedy,
|
||||
3: GC idle AT, 4: GC urgent high, 5: GC urgent low)
|
||||
3: GC idle AT, 4: GC urgent high, 5: GC urgent low 6: GC urgent mid)
|
||||
You can re-initialize this value to "0".
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/gc_segment_mode
|
||||
@@ -540,3 +574,9 @@ Contact: "Daeho Jeong" <daehojeong@google.com>
|
||||
Description: You can set the trial count limit for GC urgent high mode with this value.
|
||||
If GC thread gets to the limit, the mode will turn back to GC normal mode.
|
||||
By default, the value is zero, which means there is no limit like before.
|
||||
|
||||
What: /sys/fs/f2fs/<disk>/max_roll_forward_node_blocks
|
||||
Date: January 2022
|
||||
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
|
||||
Description: Controls max # of node block writes to be used for roll forward
|
||||
recovery. This can limit the roll forward recovery time.
|
||||
|
||||
@@ -23,11 +23,11 @@ on it as usual. The `DAX` code currently only supports files with a block
|
||||
size equal to your kernel's `PAGE_SIZE`, so you may need to specify a block
|
||||
size when creating the filesystem.
|
||||
|
||||
Currently 4 filesystems support `DAX`: ext2, ext4, xfs and virtiofs.
|
||||
Currently 5 filesystems support `DAX`: ext2, ext4, xfs, virtiofs and erofs.
|
||||
Enabling `DAX` on them is different.
|
||||
|
||||
Enabling DAX on ext2
|
||||
--------------------
|
||||
Enabling DAX on ext2 and erofs
|
||||
------------------------------
|
||||
|
||||
When mounting the filesystem, use the ``-o dax`` option on the command line or
|
||||
add 'dax' to the options in ``/etc/fstab``. This works to enable `DAX` on all files
|
||||
|
||||
@@ -40,7 +40,7 @@ Here is the main features of EROFS:
|
||||
Inode metadata size 32 bytes 64 bytes
|
||||
Max file size 4 GB 16 EB (also limited by max. vol size)
|
||||
Max uids/gids 65536 4294967296
|
||||
File change time no yes (64 + 32-bit timestamp)
|
||||
Per-inode timestamp no yes (64 + 32-bit timestamp)
|
||||
Max hardlinks 65536 4294967296
|
||||
Metadata reserved 4 bytes 14 bytes
|
||||
===================== ============ =====================================
|
||||
|
||||
@@ -39,7 +39,7 @@ For 32-bit filesystems, limits are as follows:
|
||||
- 4TiB
|
||||
- 8TiB
|
||||
- 16TiB
|
||||
- 256PiB
|
||||
- 256TiB
|
||||
* - Blocks Per Block Group
|
||||
- 8,192
|
||||
- 16,384
|
||||
|
||||
@@ -438,13 +438,13 @@ prototypes::
|
||||
locking rules:
|
||||
|
||||
====================== ============= ================= =========
|
||||
ops inode->i_lock blocked_lock_lock may block
|
||||
ops flc_lock blocked_lock_lock may block
|
||||
====================== ============= ================= =========
|
||||
lm_notify: yes yes no
|
||||
lm_notify: no yes no
|
||||
lm_grant: no no no
|
||||
lm_break: yes no no
|
||||
lm_change yes no no
|
||||
lm_breaker_owns_lease: no no no
|
||||
lm_breaker_owns_lease: yes no no
|
||||
====================== ============= ================= =========
|
||||
|
||||
buffer_head
|
||||
|
||||
@@ -3205,6 +3205,7 @@ ATOMIC INFRASTRUCTURE
|
||||
M: Will Deacon <will@kernel.org>
|
||||
M: Peter Zijlstra <peterz@infradead.org>
|
||||
R: Boqun Feng <boqun.feng@gmail.com>
|
||||
R: Mark Rutland <mark.rutland@arm.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: arch/*/include/asm/atomic*.h
|
||||
|
||||
@@ -62,7 +62,6 @@ CONFIG_TMPFS=y
|
||||
CONFIG_NFS_FS=m
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
|
||||
@@ -258,7 +258,6 @@ CONFIG_MINIX_FS=m
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ASCII=m
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
|
||||
@@ -309,7 +309,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
CONFIG_SMB_FS=m
|
||||
CONFIG_CIFS=m
|
||||
|
||||
@@ -283,7 +283,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
CONFIG_SMB_FS=m
|
||||
CONFIG_CIFS=m
|
||||
|
||||
@@ -79,7 +79,6 @@ CONFIG_CRAMFS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
|
||||
@@ -94,7 +94,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
|
||||
@@ -213,7 +213,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
|
||||
@@ -59,7 +59,6 @@ CONFIG_CRAMFS=m
|
||||
CONFIG_NFS_FS=m
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
CONFIG_NLS_CODEPAGE_850=m
|
||||
|
||||
@@ -71,7 +71,6 @@ CONFIG_NFS_V3=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_SMB_FS=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
|
||||
@@ -86,7 +86,6 @@ CONFIG_ROMFS_FS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_850=m
|
||||
CONFIG_NLS_ISO8859_1=m
|
||||
CONFIG_MAGIC_SYSRQ=y
|
||||
|
||||
@@ -145,7 +145,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
CONFIG_NLS_CODEPAGE_850=m
|
||||
|
||||
@@ -160,7 +160,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
CONFIG_NLS_CODEPAGE_850=m
|
||||
|
||||
@@ -106,7 +106,6 @@ CONFIG_HUGETLBFS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_CODEPAGE_737=y
|
||||
CONFIG_NLS_CODEPAGE_775=y
|
||||
|
||||
@@ -498,7 +498,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -455,7 +455,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -475,7 +475,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -447,7 +447,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -457,7 +457,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -477,7 +477,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -563,7 +563,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -446,7 +446,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -447,7 +447,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -464,7 +464,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -446,7 +446,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -445,7 +445,6 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
|
||||
@@ -69,6 +69,5 @@ CONFIG_CONFIGFS_FS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
CONFIG_LIBCRC32C=y
|
||||
|
||||
@@ -159,7 +159,6 @@ CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
# CONFIG_RPCSEC_GSS_KRB5 is not set
|
||||
CONFIG_NLS_ISO8859_8=m
|
||||
|
||||
@@ -154,7 +154,6 @@ CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
# CONFIG_RPCSEC_GSS_KRB5 is not set
|
||||
CONFIG_NLS_ISO8859_8=m
|
||||
|
||||
@@ -154,7 +154,6 @@ CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
# CONFIG_RPCSEC_GSS_KRB5 is not set
|
||||
CONFIG_NLS_ISO8859_8=m
|
||||
|
||||
@@ -269,7 +269,6 @@ CONFIG_UFS_FS=m
|
||||
CONFIG_NFS_FS=m
|
||||
CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NFSD_V3_ACL=y
|
||||
CONFIG_CIFS=m
|
||||
CONFIG_CIFS_UPCALL=y
|
||||
|
||||
@@ -112,7 +112,6 @@ CONFIG_CONFIGFS_FS=y
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
|
||||
@@ -92,5 +92,4 @@ CONFIG_TMPFS=y
|
||||
CONFIG_UFS_FS=m
|
||||
CONFIG_NFS_FS=m
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
|
||||
@@ -363,7 +363,6 @@ CONFIG_UFS_FS=m
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
CONFIG_NLS_CODEPAGE_737=m
|
||||
CONFIG_NLS_CODEPAGE_775=m
|
||||
|
||||
@@ -371,7 +371,6 @@ CONFIG_UFS_FS=m
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
CONFIG_NLS_CODEPAGE_737=m
|
||||
CONFIG_NLS_CODEPAGE_775=m
|
||||
|
||||
@@ -370,7 +370,6 @@ CONFIG_UFS_FS=m
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
CONFIG_NLS_CODEPAGE_737=m
|
||||
CONFIG_NLS_CODEPAGE_775=m
|
||||
|
||||
@@ -354,7 +354,6 @@ CONFIG_SYSV_FS=m
|
||||
CONFIG_UFS_FS=m
|
||||
CONFIG_NFS_FS=m
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
CONFIG_CODA_FS=m
|
||||
CONFIG_AFS_FS=m
|
||||
|
||||
@@ -72,6 +72,5 @@ CONFIG_ROMFS_FS=m
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CMDLINE_BOOL=y
|
||||
CONFIG_CMDLINE="cca=3 mem=64M console=ttyVR0,115200 ip=any root=/dev/nfs"
|
||||
|
||||
@@ -67,6 +67,5 @@ CONFIG_ROMFS_FS=m
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CMDLINE_BOOL=y
|
||||
CONFIG_CMDLINE="cca=3 mem=32M console=ttyVR0,115200"
|
||||
|
||||
@@ -77,7 +77,6 @@ CONFIG_ROMFS_FS=m
|
||||
CONFIG_NFS_FS=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_FONTS=y
|
||||
CONFIG_FONT_8x8=y
|
||||
CONFIG_FONT_8x16=y
|
||||
|
||||
@@ -63,6 +63,5 @@ CONFIG_TMPFS=y
|
||||
CONFIG_TMPFS_POSIX_ACL=y
|
||||
CONFIG_NFS_FS=m
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CMDLINE_BOOL=y
|
||||
CONFIG_CMDLINE="console=ttyVR0,19200 ide0=0x170,0x376,49 mem=16M"
|
||||
|
||||
@@ -210,7 +210,6 @@ CONFIG_TMPFS_XATTR=y
|
||||
CONFIG_NFS_FS=m
|
||||
# CONFIG_NFS_V2 is not set
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
CONFIG_CIFS_XATTR=y
|
||||
CONFIG_CIFS_POSIX=y
|
||||
|
||||
@@ -120,7 +120,6 @@ CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
CONFIG_NLS_CODEPAGE_932=m
|
||||
|
||||
@@ -101,7 +101,6 @@ CONFIG_NFS_V3_ACL=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_CIFS=m
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
|
||||
@@ -93,7 +93,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_CODEPAGE_932=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
|
||||
@@ -123,7 +123,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_CODEPAGE_932=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
|
||||
@@ -108,7 +108,6 @@ CONFIG_UFS_FS=m
|
||||
CONFIG_NFS_FS=m
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_SMB_FS=m
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_CODEPAGE_932=y
|
||||
|
||||
@@ -120,7 +120,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_ASCII=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
|
||||
@@ -122,7 +122,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_CODEPAGE_932=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
|
||||
@@ -75,7 +75,6 @@ CONFIG_NFS_V3=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
CONFIG_NLS_CODEPAGE_437=m
|
||||
CONFIG_NLS_CODEPAGE_737=m
|
||||
|
||||
@@ -129,7 +129,6 @@ CONFIG_NFS_V3=y
|
||||
CONFIG_NFS_V4=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_NLS_CODEPAGE_437=y
|
||||
CONFIG_NLS_CODEPAGE_932=y
|
||||
CONFIG_NLS_ISO8859_1=y
|
||||
|
||||
@@ -239,7 +239,6 @@ CONFIG_NFS_FS=y
|
||||
CONFIG_NFS_V3=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=y
|
||||
CONFIG_NFSD_V3=y
|
||||
CONFIG_SMB_FS=m
|
||||
CONFIG_CIFS=m
|
||||
CONFIG_PARTITION_ADVANCED=y
|
||||
|
||||
@@ -181,6 +181,27 @@ static struct event_constraint intel_gen_event_constraints[] __read_mostly =
|
||||
EVENT_CONSTRAINT_END
|
||||
};
|
||||
|
||||
static struct event_constraint intel_v5_gen_event_constraints[] __read_mostly =
|
||||
{
|
||||
FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
|
||||
FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
|
||||
FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
|
||||
FIXED_EVENT_CONSTRAINT(0x0400, 3), /* SLOTS */
|
||||
FIXED_EVENT_CONSTRAINT(0x0500, 4),
|
||||
FIXED_EVENT_CONSTRAINT(0x0600, 5),
|
||||
FIXED_EVENT_CONSTRAINT(0x0700, 6),
|
||||
FIXED_EVENT_CONSTRAINT(0x0800, 7),
|
||||
FIXED_EVENT_CONSTRAINT(0x0900, 8),
|
||||
FIXED_EVENT_CONSTRAINT(0x0a00, 9),
|
||||
FIXED_EVENT_CONSTRAINT(0x0b00, 10),
|
||||
FIXED_EVENT_CONSTRAINT(0x0c00, 11),
|
||||
FIXED_EVENT_CONSTRAINT(0x0d00, 12),
|
||||
FIXED_EVENT_CONSTRAINT(0x0e00, 13),
|
||||
FIXED_EVENT_CONSTRAINT(0x0f00, 14),
|
||||
FIXED_EVENT_CONSTRAINT(0x1000, 15),
|
||||
EVENT_CONSTRAINT_END
|
||||
};
|
||||
|
||||
static struct event_constraint intel_slm_event_constraints[] __read_mostly =
|
||||
{
|
||||
FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
|
||||
@@ -6308,7 +6329,9 @@ __init int intel_pmu_init(void)
|
||||
pr_cont("generic architected perfmon v1, ");
|
||||
name = "generic_arch_v1";
|
||||
break;
|
||||
default:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
/*
|
||||
* default constraints for v2 and up
|
||||
*/
|
||||
@@ -6316,6 +6339,21 @@ __init int intel_pmu_init(void)
|
||||
pr_cont("generic architected perfmon, ");
|
||||
name = "generic_arch_v2+";
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* The default constraints for v5 and up can support up to
|
||||
* 16 fixed counters. For the fixed counters 4 and later,
|
||||
* the pseudo-encoding is applied.
|
||||
* The constraints may be cut according to the CPUID enumeration
|
||||
* by inserting the EVENT_CONSTRAINT_END.
|
||||
*/
|
||||
if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED)
|
||||
x86_pmu.num_counters_fixed = INTEL_PMC_MAX_FIXED;
|
||||
intel_v5_gen_event_constraints[x86_pmu.num_counters_fixed].weight = -1;
|
||||
x86_pmu.event_constraints = intel_v5_gen_event_constraints;
|
||||
pr_cont("generic architected perfmon, ");
|
||||
name = "generic_arch_v5+";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1203,7 +1203,10 @@ static void intel_pmu_pebs_via_pt_enable(struct perf_event *event)
|
||||
if (hwc->idx >= INTEL_PMC_IDX_FIXED) {
|
||||
base = MSR_RELOAD_FIXED_CTR0;
|
||||
idx = hwc->idx - INTEL_PMC_IDX_FIXED;
|
||||
value = ds->pebs_event_reset[MAX_PEBS_EVENTS + idx];
|
||||
if (x86_pmu.intel_cap.pebs_format < 5)
|
||||
value = ds->pebs_event_reset[MAX_PEBS_EVENTS_FMT4 + idx];
|
||||
else
|
||||
value = ds->pebs_event_reset[MAX_PEBS_EVENTS + idx];
|
||||
}
|
||||
wrmsrl(base + idx, value);
|
||||
}
|
||||
@@ -1232,8 +1235,12 @@ void intel_pmu_pebs_enable(struct perf_event *event)
|
||||
}
|
||||
}
|
||||
|
||||
if (idx >= INTEL_PMC_IDX_FIXED)
|
||||
idx = MAX_PEBS_EVENTS + (idx - INTEL_PMC_IDX_FIXED);
|
||||
if (idx >= INTEL_PMC_IDX_FIXED) {
|
||||
if (x86_pmu.intel_cap.pebs_format < 5)
|
||||
idx = MAX_PEBS_EVENTS_FMT4 + (idx - INTEL_PMC_IDX_FIXED);
|
||||
else
|
||||
idx = MAX_PEBS_EVENTS + (idx - INTEL_PMC_IDX_FIXED);
|
||||
}
|
||||
|
||||
/*
|
||||
* Use auto-reload if possible to save a MSR write in the PMI.
|
||||
@@ -2204,6 +2211,7 @@ void __init intel_ds_init(void)
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 5:
|
||||
x86_pmu.drain_pebs = intel_pmu_drain_pebs_icl;
|
||||
x86_pmu.pebs_record_size = sizeof(struct pebs_basic);
|
||||
if (x86_pmu.intel_cap.pebs_baseline) {
|
||||
|
||||
@@ -1329,10 +1329,10 @@ static int branch_map[X86_BR_TYPE_MAP_MAX] = {
|
||||
PERF_BR_SYSCALL, /* X86_BR_SYSCALL */
|
||||
PERF_BR_SYSRET, /* X86_BR_SYSRET */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_INT */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_IRET */
|
||||
PERF_BR_ERET, /* X86_BR_IRET */
|
||||
PERF_BR_COND, /* X86_BR_JCC */
|
||||
PERF_BR_UNCOND, /* X86_BR_JMP */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_IRQ */
|
||||
PERF_BR_IRQ, /* X86_BR_IRQ */
|
||||
PERF_BR_IND_CALL, /* X86_BR_IND_CALL */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_ABORT */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_IN_TX */
|
||||
|
||||
+57
-14
@@ -13,6 +13,8 @@
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
@@ -57,6 +59,8 @@ static struct pt_cap_desc {
|
||||
PT_CAP(mtc, 0, CPUID_EBX, BIT(3)),
|
||||
PT_CAP(ptwrite, 0, CPUID_EBX, BIT(4)),
|
||||
PT_CAP(power_event_trace, 0, CPUID_EBX, BIT(5)),
|
||||
PT_CAP(event_trace, 0, CPUID_EBX, BIT(7)),
|
||||
PT_CAP(tnt_disable, 0, CPUID_EBX, BIT(8)),
|
||||
PT_CAP(topa_output, 0, CPUID_ECX, BIT(0)),
|
||||
PT_CAP(topa_multiple_entries, 0, CPUID_ECX, BIT(1)),
|
||||
PT_CAP(single_range_output, 0, CPUID_ECX, BIT(2)),
|
||||
@@ -108,6 +112,8 @@ PMU_FORMAT_ATTR(tsc, "config:10" );
|
||||
PMU_FORMAT_ATTR(noretcomp, "config:11" );
|
||||
PMU_FORMAT_ATTR(ptw, "config:12" );
|
||||
PMU_FORMAT_ATTR(branch, "config:13" );
|
||||
PMU_FORMAT_ATTR(event, "config:31" );
|
||||
PMU_FORMAT_ATTR(notnt, "config:55" );
|
||||
PMU_FORMAT_ATTR(mtc_period, "config:14-17" );
|
||||
PMU_FORMAT_ATTR(cyc_thresh, "config:19-22" );
|
||||
PMU_FORMAT_ATTR(psb_period, "config:24-27" );
|
||||
@@ -116,6 +122,8 @@ static struct attribute *pt_formats_attr[] = {
|
||||
&format_attr_pt.attr,
|
||||
&format_attr_cyc.attr,
|
||||
&format_attr_pwr_evt.attr,
|
||||
&format_attr_event.attr,
|
||||
&format_attr_notnt.attr,
|
||||
&format_attr_fup_on_ptw.attr,
|
||||
&format_attr_mtc.attr,
|
||||
&format_attr_tsc.attr,
|
||||
@@ -296,6 +304,8 @@ fail:
|
||||
RTIT_CTL_CYC_PSB | \
|
||||
RTIT_CTL_MTC | \
|
||||
RTIT_CTL_PWR_EVT_EN | \
|
||||
RTIT_CTL_EVENT_EN | \
|
||||
RTIT_CTL_NOTNT | \
|
||||
RTIT_CTL_FUP_ON_PTW | \
|
||||
RTIT_CTL_PTW_EN)
|
||||
|
||||
@@ -350,6 +360,14 @@ static bool pt_event_valid(struct perf_event *event)
|
||||
!intel_pt_validate_hw_cap(PT_CAP_power_event_trace))
|
||||
return false;
|
||||
|
||||
if (config & RTIT_CTL_EVENT_EN &&
|
||||
!intel_pt_validate_hw_cap(PT_CAP_event_trace))
|
||||
return false;
|
||||
|
||||
if (config & RTIT_CTL_NOTNT &&
|
||||
!intel_pt_validate_hw_cap(PT_CAP_tnt_disable))
|
||||
return false;
|
||||
|
||||
if (config & RTIT_CTL_PTW) {
|
||||
if (!intel_pt_validate_hw_cap(PT_CAP_ptwrite))
|
||||
return false;
|
||||
@@ -472,7 +490,7 @@ static u64 pt_config_filters(struct perf_event *event)
|
||||
pt->filters.filter[range].msr_b = filter->msr_b;
|
||||
}
|
||||
|
||||
rtit_ctl |= filter->config << pt_address_ranges[range].reg_off;
|
||||
rtit_ctl |= (u64)filter->config << pt_address_ranges[range].reg_off;
|
||||
}
|
||||
|
||||
return rtit_ctl;
|
||||
@@ -1348,11 +1366,27 @@ static void pt_addr_filters_fini(struct perf_event *event)
|
||||
event->hw.addr_filters = NULL;
|
||||
}
|
||||
|
||||
static inline bool valid_kernel_ip(unsigned long ip)
|
||||
#ifdef CONFIG_X86_64
|
||||
/* Clamp to a canonical address greater-than-or-equal-to the address given */
|
||||
static u64 clamp_to_ge_canonical_addr(u64 vaddr, u8 vaddr_bits)
|
||||
{
|
||||
return virt_addr_valid(ip) && kernel_ip(ip);
|
||||
return __is_canonical_address(vaddr, vaddr_bits) ?
|
||||
vaddr :
|
||||
-BIT_ULL(vaddr_bits - 1);
|
||||
}
|
||||
|
||||
/* Clamp to a canonical address less-than-or-equal-to the address given */
|
||||
static u64 clamp_to_le_canonical_addr(u64 vaddr, u8 vaddr_bits)
|
||||
{
|
||||
return __is_canonical_address(vaddr, vaddr_bits) ?
|
||||
vaddr :
|
||||
BIT_ULL(vaddr_bits - 1) - 1;
|
||||
}
|
||||
#else
|
||||
#define clamp_to_ge_canonical_addr(x, y) (x)
|
||||
#define clamp_to_le_canonical_addr(x, y) (x)
|
||||
#endif
|
||||
|
||||
static int pt_event_addr_filters_validate(struct list_head *filters)
|
||||
{
|
||||
struct perf_addr_filter *filter;
|
||||
@@ -1367,14 +1401,6 @@ static int pt_event_addr_filters_validate(struct list_head *filters)
|
||||
filter->action == PERF_ADDR_FILTER_ACTION_START)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!filter->path.dentry) {
|
||||
if (!valid_kernel_ip(filter->offset))
|
||||
return -EINVAL;
|
||||
|
||||
if (!valid_kernel_ip(filter->offset + filter->size))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (++range > intel_pt_validate_hw_cap(PT_CAP_num_address_ranges))
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -1398,9 +1424,26 @@ static void pt_event_addr_filters_sync(struct perf_event *event)
|
||||
if (filter->path.dentry && !fr[range].start) {
|
||||
msr_a = msr_b = 0;
|
||||
} else {
|
||||
/* apply the offset */
|
||||
msr_a = fr[range].start;
|
||||
msr_b = msr_a + fr[range].size - 1;
|
||||
unsigned long n = fr[range].size - 1;
|
||||
unsigned long a = fr[range].start;
|
||||
unsigned long b;
|
||||
|
||||
if (a > ULONG_MAX - n)
|
||||
b = ULONG_MAX;
|
||||
else
|
||||
b = a + n;
|
||||
/*
|
||||
* Apply the offset. 64-bit addresses written to the
|
||||
* MSRs must be canonical, but the range can encompass
|
||||
* non-canonical addresses. Since software cannot
|
||||
* execute at non-canonical addresses, adjusting to
|
||||
* canonical addresses does not affect the result of the
|
||||
* address filter.
|
||||
*/
|
||||
msr_a = clamp_to_ge_canonical_addr(a, boot_cpu_data.x86_virt_bits);
|
||||
msr_b = clamp_to_le_canonical_addr(b, boot_cpu_data.x86_virt_bits);
|
||||
if (msr_b < msr_a)
|
||||
msr_a = msr_b = 0;
|
||||
}
|
||||
|
||||
filters->filter[range].msr_a = msr_a;
|
||||
|
||||
@@ -215,10 +215,18 @@ static int parse_discovery_table(struct pci_dev *dev, int die,
|
||||
|
||||
pci_read_config_dword(dev, bar_offset, &val);
|
||||
|
||||
if (val & UNCORE_DISCOVERY_MASK)
|
||||
if (val & ~PCI_BASE_ADDRESS_MEM_MASK & ~PCI_BASE_ADDRESS_MEM_TYPE_64)
|
||||
return -EINVAL;
|
||||
|
||||
addr = (resource_size_t)(val & ~UNCORE_DISCOVERY_MASK);
|
||||
addr = (resource_size_t)(val & PCI_BASE_ADDRESS_MEM_MASK);
|
||||
#ifdef CONFIG_PHYS_ADDR_T_64BIT
|
||||
if ((val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64) {
|
||||
u32 val2;
|
||||
|
||||
pci_read_config_dword(dev, bar_offset + 4, &val2);
|
||||
addr |= ((resource_size_t)val2) << 32;
|
||||
}
|
||||
#endif
|
||||
size = UNCORE_DISCOVERY_GLOBAL_MAP_SIZE;
|
||||
io_addr = ioremap(addr, size);
|
||||
if (!io_addr)
|
||||
@@ -444,7 +452,7 @@ static struct intel_uncore_ops generic_uncore_pci_ops = {
|
||||
|
||||
#define UNCORE_GENERIC_MMIO_SIZE 0x4000
|
||||
|
||||
static unsigned int generic_uncore_mmio_box_ctl(struct intel_uncore_box *box)
|
||||
static u64 generic_uncore_mmio_box_ctl(struct intel_uncore_box *box)
|
||||
{
|
||||
struct intel_uncore_type *type = box->pmu->type;
|
||||
|
||||
@@ -456,7 +464,7 @@ static unsigned int generic_uncore_mmio_box_ctl(struct intel_uncore_box *box)
|
||||
|
||||
void intel_generic_uncore_mmio_init_box(struct intel_uncore_box *box)
|
||||
{
|
||||
unsigned int box_ctl = generic_uncore_mmio_box_ctl(box);
|
||||
u64 box_ctl = generic_uncore_mmio_box_ctl(box);
|
||||
struct intel_uncore_type *type = box->pmu->type;
|
||||
resource_size_t addr;
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
#define UNCORE_DISCOVERY_BIR_BASE 0x10
|
||||
/* Discovery table BAR step */
|
||||
#define UNCORE_DISCOVERY_BIR_STEP 0x4
|
||||
/* Mask of the discovery table offset */
|
||||
#define UNCORE_DISCOVERY_MASK 0xf
|
||||
/* Global discovery table size */
|
||||
#define UNCORE_DISCOVERY_GLOBAL_MAP_SIZE 0x20
|
||||
|
||||
|
||||
@@ -20,11 +20,21 @@ static __always_inline bool arch_cpu_online(int cpu)
|
||||
{
|
||||
return arch_test_bit(cpu, cpumask_bits(cpu_online_mask));
|
||||
}
|
||||
|
||||
static __always_inline void arch_cpumask_clear_cpu(int cpu, struct cpumask *dstp)
|
||||
{
|
||||
arch_clear_bit(cpumask_check(cpu), cpumask_bits(dstp));
|
||||
}
|
||||
#else
|
||||
static __always_inline bool arch_cpu_online(int cpu)
|
||||
{
|
||||
return cpu == 0;
|
||||
}
|
||||
|
||||
static __always_inline void arch_cpumask_clear_cpu(int cpu, struct cpumask *dstp)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define arch_cpu_is_offline(cpu) unlikely(!arch_cpu_online(cpu))
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
#define PEBS_BUFFER_SIZE (PAGE_SIZE << 4)
|
||||
|
||||
/* The maximal number of PEBS events: */
|
||||
#define MAX_PEBS_EVENTS 8
|
||||
#define MAX_FIXED_PEBS_EVENTS 4
|
||||
#define MAX_PEBS_EVENTS_FMT4 8
|
||||
#define MAX_PEBS_EVENTS 32
|
||||
#define MAX_FIXED_PEBS_EVENTS 16
|
||||
|
||||
/*
|
||||
* A debug store configuration.
|
||||
|
||||
@@ -13,6 +13,8 @@ enum pt_capabilities {
|
||||
PT_CAP_mtc,
|
||||
PT_CAP_ptwrite,
|
||||
PT_CAP_power_event_trace,
|
||||
PT_CAP_event_trace,
|
||||
PT_CAP_tnt_disable,
|
||||
PT_CAP_topa_output,
|
||||
PT_CAP_topa_multiple_entries,
|
||||
PT_CAP_single_range_output,
|
||||
|
||||
@@ -498,6 +498,7 @@ struct kvm_pmc {
|
||||
bool intr;
|
||||
};
|
||||
|
||||
#define KVM_PMC_MAX_FIXED 3
|
||||
struct kvm_pmu {
|
||||
unsigned nr_arch_gp_counters;
|
||||
unsigned nr_arch_fixed_counters;
|
||||
@@ -511,7 +512,7 @@ struct kvm_pmu {
|
||||
u64 reserved_bits;
|
||||
u8 version;
|
||||
struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC];
|
||||
struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED];
|
||||
struct kvm_pmc fixed_counters[KVM_PMC_MAX_FIXED];
|
||||
struct irq_work irq_work;
|
||||
DECLARE_BITMAP(reprogram_pmi, X86_PMC_IDX_MAX);
|
||||
DECLARE_BITMAP(all_valid_pmc_idx, X86_PMC_IDX_MAX);
|
||||
|
||||
@@ -205,6 +205,8 @@
|
||||
#define RTIT_CTL_DISRETC BIT(11)
|
||||
#define RTIT_CTL_PTW_EN BIT(12)
|
||||
#define RTIT_CTL_BRANCH_EN BIT(13)
|
||||
#define RTIT_CTL_EVENT_EN BIT(31)
|
||||
#define RTIT_CTL_NOTNT BIT_ULL(55)
|
||||
#define RTIT_CTL_MTC_RANGE_OFFSET 14
|
||||
#define RTIT_CTL_MTC_RANGE (0x0full << RTIT_CTL_MTC_RANGE_OFFSET)
|
||||
#define RTIT_CTL_CYC_THRESH_OFFSET 19
|
||||
|
||||
@@ -71,6 +71,16 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
|
||||
extern bool __virt_addr_valid(unsigned long kaddr);
|
||||
#define virt_addr_valid(kaddr) __virt_addr_valid((unsigned long) (kaddr))
|
||||
|
||||
static __always_inline u64 __canonical_address(u64 vaddr, u8 vaddr_bits)
|
||||
{
|
||||
return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
|
||||
}
|
||||
|
||||
static __always_inline u64 __is_canonical_address(u64 vaddr, u8 vaddr_bits)
|
||||
{
|
||||
return __canonical_address(vaddr, vaddr_bits) == vaddr;
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#include <asm-generic/memory_model.h>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
#define INTEL_PMC_MAX_GENERIC 32
|
||||
#define INTEL_PMC_MAX_FIXED 4
|
||||
#define INTEL_PMC_MAX_FIXED 16
|
||||
#define INTEL_PMC_IDX_FIXED 32
|
||||
|
||||
#define X86_PMC_IDX_MAX 64
|
||||
|
||||
@@ -137,7 +137,7 @@ static __always_inline int user_mode(struct pt_regs *regs)
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline int v8086_mode(struct pt_regs *regs)
|
||||
static __always_inline int v8086_mode(struct pt_regs *regs)
|
||||
{
|
||||
#ifdef CONFIG_X86_32
|
||||
return (regs->flags & X86_VM_MASK);
|
||||
|
||||
@@ -879,7 +879,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
|
||||
eax.split.bit_width = cap.bit_width_gp;
|
||||
eax.split.mask_length = cap.events_mask_len;
|
||||
|
||||
edx.split.num_counters_fixed = min(cap.num_counters_fixed, MAX_FIXED_COUNTERS);
|
||||
edx.split.num_counters_fixed =
|
||||
min(cap.num_counters_fixed, KVM_PMC_MAX_FIXED);
|
||||
edx.split.bit_width_fixed = cap.bit_width_fixed;
|
||||
if (cap.version)
|
||||
edx.split.anythread_deprecated = 1;
|
||||
|
||||
@@ -680,7 +680,7 @@ static inline u8 ctxt_virt_addr_bits(struct x86_emulate_ctxt *ctxt)
|
||||
static inline bool emul_is_noncanonical_address(u64 la,
|
||||
struct x86_emulate_ctxt *ctxt)
|
||||
{
|
||||
return get_canonical(la, ctxt_virt_addr_bits(ctxt)) != la;
|
||||
return !__is_canonical_address(la, ctxt_virt_addr_bits(ctxt));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -730,7 +730,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
|
||||
case X86EMUL_MODE_PROT64:
|
||||
*linear = la;
|
||||
va_bits = ctxt_virt_addr_bits(ctxt);
|
||||
if (get_canonical(la, va_bits) != la)
|
||||
if (!__is_canonical_address(la, va_bits))
|
||||
goto bad;
|
||||
|
||||
*max_size = min_t(u64, ~0u, (1ull << va_bits) - la);
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#define VMWARE_BACKDOOR_PMC_REAL_TIME 0x10001
|
||||
#define VMWARE_BACKDOOR_PMC_APPARENT_TIME 0x10002
|
||||
|
||||
#define MAX_FIXED_COUNTERS 3
|
||||
|
||||
struct kvm_event_hw_type_mapping {
|
||||
u8 eventsel;
|
||||
u8 unit_mask;
|
||||
|
||||
@@ -565,7 +565,7 @@ static void intel_pmu_init(struct kvm_vcpu *vcpu)
|
||||
pmu->gp_counters[i].current_config = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < INTEL_PMC_MAX_FIXED; i++) {
|
||||
for (i = 0; i < KVM_PMC_MAX_FIXED; i++) {
|
||||
pmu->fixed_counters[i].type = KVM_PMC_FIXED;
|
||||
pmu->fixed_counters[i].vcpu = vcpu;
|
||||
pmu->fixed_counters[i].idx = i + INTEL_PMC_IDX_FIXED;
|
||||
@@ -591,7 +591,7 @@ static void intel_pmu_reset(struct kvm_vcpu *vcpu)
|
||||
pmc->counter = pmc->eventsel = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < INTEL_PMC_MAX_FIXED; i++) {
|
||||
for (i = 0; i < KVM_PMC_MAX_FIXED; i++) {
|
||||
pmc = &pmu->fixed_counters[i];
|
||||
|
||||
pmc_stop_counter(pmc);
|
||||
|
||||
+2
-2
@@ -1749,7 +1749,7 @@ static int __kvm_set_msr(struct kvm_vcpu *vcpu, u32 index, u64 data,
|
||||
* value, and that something deterministic happens if the guest
|
||||
* invokes 64-bit SYSENTER.
|
||||
*/
|
||||
data = get_canonical(data, vcpu_virt_addr_bits(vcpu));
|
||||
data = __canonical_address(data, vcpu_virt_addr_bits(vcpu));
|
||||
break;
|
||||
case MSR_TSC_AUX:
|
||||
if (!kvm_is_supported_user_return_msr(MSR_TSC_AUX))
|
||||
@@ -6529,7 +6529,7 @@ static void kvm_init_msr_list(void)
|
||||
u32 dummy[2];
|
||||
unsigned i;
|
||||
|
||||
BUILD_BUG_ON_MSG(INTEL_PMC_MAX_FIXED != 4,
|
||||
BUILD_BUG_ON_MSG(KVM_PMC_MAX_FIXED != 3,
|
||||
"Please update the fixed PMCs in msrs_to_saved_all[]");
|
||||
|
||||
perf_get_x86_pmu_capability(&x86_pmu);
|
||||
|
||||
+1
-6
@@ -166,14 +166,9 @@ static inline u8 vcpu_virt_addr_bits(struct kvm_vcpu *vcpu)
|
||||
return kvm_read_cr4_bits(vcpu, X86_CR4_LA57) ? 57 : 48;
|
||||
}
|
||||
|
||||
static inline u64 get_canonical(u64 la, u8 vaddr_bits)
|
||||
{
|
||||
return ((int64_t)la << (64 - vaddr_bits)) >> (64 - vaddr_bits);
|
||||
}
|
||||
|
||||
static inline bool is_noncanonical_address(u64 la, struct kvm_vcpu *vcpu)
|
||||
{
|
||||
return get_canonical(la, vcpu_virt_addr_bits(vcpu)) != la;
|
||||
return !__is_canonical_address(la, vcpu_virt_addr_bits(vcpu));
|
||||
}
|
||||
|
||||
static inline void vcpu_cache_mmio_info(struct kvm_vcpu *vcpu,
|
||||
|
||||
@@ -4,11 +4,6 @@
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
static __always_inline u64 canonical_address(u64 vaddr, u8 vaddr_bits)
|
||||
{
|
||||
return ((s64)vaddr << (64 - vaddr_bits)) >> (64 - vaddr_bits);
|
||||
}
|
||||
|
||||
bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
|
||||
{
|
||||
unsigned long vaddr = (unsigned long)unsafe_src;
|
||||
@@ -19,7 +14,7 @@ bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
|
||||
* we also need to include the userspace guard page.
|
||||
*/
|
||||
return vaddr >= TASK_SIZE_MAX + PAGE_SIZE &&
|
||||
canonical_address(vaddr, boot_cpu_data.x86_virt_bits) == vaddr;
|
||||
__is_canonical_address(vaddr, boot_cpu_data.x86_virt_bits);
|
||||
}
|
||||
#else
|
||||
bool copy_from_kernel_nofault_allowed(const void *unsafe_src, size_t size)
|
||||
|
||||
+1
-1
@@ -345,7 +345,7 @@ config LOCKD
|
||||
|
||||
config LOCKD_V4
|
||||
bool
|
||||
depends on NFSD_V3 || NFS_V3
|
||||
depends on NFSD || NFS_V3
|
||||
depends on FILE_LOCKING
|
||||
default y
|
||||
|
||||
|
||||
+5
-2
@@ -789,11 +789,13 @@ static int add_missing_keys(struct btrfs_fs_info *fs_info,
|
||||
if (IS_ERR(eb)) {
|
||||
free_pref(ref);
|
||||
return PTR_ERR(eb);
|
||||
} else if (!extent_buffer_uptodate(eb)) {
|
||||
}
|
||||
if (!extent_buffer_uptodate(eb)) {
|
||||
free_pref(ref);
|
||||
free_extent_buffer(eb);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (lock)
|
||||
btrfs_tree_read_lock(eb);
|
||||
if (btrfs_header_level(eb) == 0)
|
||||
@@ -1335,7 +1337,8 @@ again:
|
||||
if (IS_ERR(eb)) {
|
||||
ret = PTR_ERR(eb);
|
||||
goto out;
|
||||
} else if (!extent_buffer_uptodate(eb)) {
|
||||
}
|
||||
if (!extent_buffer_uptodate(eb)) {
|
||||
free_extent_buffer(eb);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
|
||||
+33
-3
@@ -1522,8 +1522,12 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
|
||||
if (!test_bit(BTRFS_FS_OPEN, &fs_info->flags))
|
||||
return;
|
||||
|
||||
if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE))
|
||||
sb_start_write(fs_info->sb);
|
||||
|
||||
if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_BALANCE)) {
|
||||
sb_end_write(fs_info->sb);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Long running balances can keep us blocked here for eternity, so
|
||||
@@ -1531,6 +1535,7 @@ void btrfs_reclaim_bgs_work(struct work_struct *work)
|
||||
*/
|
||||
if (!mutex_trylock(&fs_info->reclaim_bgs_lock)) {
|
||||
btrfs_exclop_finish(fs_info);
|
||||
sb_end_write(fs_info->sb);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1605,6 +1610,7 @@ next:
|
||||
spin_unlock(&fs_info->unused_bgs_lock);
|
||||
mutex_unlock(&fs_info->reclaim_bgs_lock);
|
||||
btrfs_exclop_finish(fs_info);
|
||||
sb_end_write(fs_info->sb);
|
||||
}
|
||||
|
||||
void btrfs_reclaim_bgs(struct btrfs_fs_info *fs_info)
|
||||
@@ -2006,6 +2012,7 @@ static int read_one_block_group(struct btrfs_fs_info *info,
|
||||
cache->length = key->offset;
|
||||
cache->used = btrfs_stack_block_group_used(bgi);
|
||||
cache->flags = btrfs_stack_block_group_flags(bgi);
|
||||
cache->global_root_id = btrfs_stack_block_group_chunk_objectid(bgi);
|
||||
|
||||
set_free_space_tree_thresholds(cache);
|
||||
|
||||
@@ -2288,7 +2295,7 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
|
||||
spin_lock(&block_group->lock);
|
||||
btrfs_set_stack_block_group_used(&bgi, block_group->used);
|
||||
btrfs_set_stack_block_group_chunk_objectid(&bgi,
|
||||
BTRFS_FIRST_CHUNK_TREE_OBJECTID);
|
||||
block_group->global_root_id);
|
||||
btrfs_set_stack_block_group_flags(&bgi, block_group->flags);
|
||||
key.objectid = block_group->start;
|
||||
key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
|
||||
@@ -2444,6 +2451,27 @@ next:
|
||||
btrfs_trans_release_chunk_metadata(trans);
|
||||
}
|
||||
|
||||
/*
|
||||
* For extent tree v2 we use the block_group_item->chunk_offset to point at our
|
||||
* global root id. For v1 it's always set to BTRFS_FIRST_CHUNK_TREE_OBJECTID.
|
||||
*/
|
||||
static u64 calculate_global_root_id(struct btrfs_fs_info *fs_info, u64 offset)
|
||||
{
|
||||
u64 div = SZ_1G;
|
||||
u64 index;
|
||||
|
||||
if (!btrfs_fs_incompat(fs_info, EXTENT_TREE_V2))
|
||||
return BTRFS_FIRST_CHUNK_TREE_OBJECTID;
|
||||
|
||||
/* If we have a smaller fs index based on 128MiB. */
|
||||
if (btrfs_super_total_bytes(fs_info->super_copy) <= (SZ_1G * 10ULL))
|
||||
div = SZ_128M;
|
||||
|
||||
offset = div64_u64(offset, div);
|
||||
div64_u64_rem(offset, fs_info->nr_global_roots, &index);
|
||||
return index;
|
||||
}
|
||||
|
||||
struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *trans,
|
||||
u64 bytes_used, u64 type,
|
||||
u64 chunk_offset, u64 size)
|
||||
@@ -2464,6 +2492,8 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
|
||||
cache->flags = type;
|
||||
cache->last_byte_to_unpin = (u64)-1;
|
||||
cache->cached = BTRFS_CACHE_FINISHED;
|
||||
cache->global_root_id = calculate_global_root_id(fs_info, cache->start);
|
||||
|
||||
if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE))
|
||||
cache->needs_free_space = 1;
|
||||
|
||||
@@ -2693,7 +2723,7 @@ static int update_block_group_item(struct btrfs_trans_handle *trans,
|
||||
bi = btrfs_item_ptr_offset(leaf, path->slots[0]);
|
||||
btrfs_set_stack_block_group_used(&bgi, cache->used);
|
||||
btrfs_set_stack_block_group_chunk_objectid(&bgi,
|
||||
BTRFS_FIRST_CHUNK_TREE_OBJECTID);
|
||||
cache->global_root_id);
|
||||
btrfs_set_stack_block_group_flags(&bgi, cache->flags);
|
||||
write_extent_buffer(leaf, &bgi, bi, sizeof(bgi));
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
|
||||
@@ -68,6 +68,7 @@ struct btrfs_block_group {
|
||||
u64 bytes_super;
|
||||
u64 flags;
|
||||
u64 cache_generation;
|
||||
u64 global_root_id;
|
||||
|
||||
/*
|
||||
* If the free space extent count exceeds this number, convert the block
|
||||
|
||||
+40
-2
@@ -13,6 +13,13 @@
|
||||
#include "ordered-data.h"
|
||||
#include "delayed-inode.h"
|
||||
|
||||
/*
|
||||
* Since we search a directory based on f_pos (struct dir_context::pos) we have
|
||||
* to start at 2 since '.' and '..' have f_pos of 0 and 1 respectively, so
|
||||
* everybody else has to start at 2 (see btrfs_real_readdir() and dir_emit_dots()).
|
||||
*/
|
||||
#define BTRFS_DIR_START_INDEX 2
|
||||
|
||||
/*
|
||||
* ordered_data_close is set by truncate when a file that used
|
||||
* to have good data has been truncated to zero. When it is set
|
||||
@@ -173,8 +180,9 @@ struct btrfs_inode {
|
||||
u64 disk_i_size;
|
||||
|
||||
/*
|
||||
* if this is a directory then index_cnt is the counter for the index
|
||||
* number for new files that are created
|
||||
* If this is a directory then index_cnt is the counter for the index
|
||||
* number for new files that are created. For an empty directory, this
|
||||
* must be initialized to BTRFS_DIR_START_INDEX.
|
||||
*/
|
||||
u64 index_cnt;
|
||||
|
||||
@@ -333,6 +341,36 @@ static inline void btrfs_set_inode_last_sub_trans(struct btrfs_inode *inode)
|
||||
spin_unlock(&inode->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Should be called while holding the inode's VFS lock in exclusive mode or in a
|
||||
* context where no one else can access the inode concurrently (during inode
|
||||
* creation or when loading an inode from disk).
|
||||
*/
|
||||
static inline void btrfs_set_inode_full_sync(struct btrfs_inode *inode)
|
||||
{
|
||||
set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags);
|
||||
/*
|
||||
* The inode may have been part of a reflink operation in the last
|
||||
* transaction that modified it, and then a fsync has reset the
|
||||
* last_reflink_trans to avoid subsequent fsyncs in the same
|
||||
* transaction to do unnecessary work. So update last_reflink_trans
|
||||
* to the last_trans value (we have to be pessimistic and assume a
|
||||
* reflink happened).
|
||||
*
|
||||
* The ->last_trans is protected by the inode's spinlock and we can
|
||||
* have a concurrent ordered extent completion update it. Also set
|
||||
* last_reflink_trans to ->last_trans only if the former is less than
|
||||
* the later, because we can be called in a context where
|
||||
* last_reflink_trans was set to the current transaction generation
|
||||
* while ->last_trans was not yet updated in the current transaction,
|
||||
* and therefore has a lower value.
|
||||
*/
|
||||
spin_lock(&inode->lock);
|
||||
if (inode->last_reflink_trans < inode->last_trans)
|
||||
inode->last_reflink_trans = inode->last_trans;
|
||||
spin_unlock(&inode->lock);
|
||||
}
|
||||
|
||||
static inline bool btrfs_inode_in_log(struct btrfs_inode *inode, u64 generation)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
+37
-26
@@ -219,7 +219,7 @@ static bool dec_and_test_compressed_bio(struct compressed_bio *cb, struct bio *b
|
||||
bi_size += bvec->bv_len;
|
||||
|
||||
if (bio->bi_status)
|
||||
cb->errors = 1;
|
||||
cb->status = bio->bi_status;
|
||||
|
||||
ASSERT(bi_size && bi_size <= cb->compressed_len);
|
||||
last_io = refcount_sub_and_test(bi_size >> fs_info->sectorsize_bits,
|
||||
@@ -234,7 +234,7 @@ static bool dec_and_test_compressed_bio(struct compressed_bio *cb, struct bio *b
|
||||
return last_io;
|
||||
}
|
||||
|
||||
static void finish_compressed_bio_read(struct compressed_bio *cb, struct bio *bio)
|
||||
static void finish_compressed_bio_read(struct compressed_bio *cb)
|
||||
{
|
||||
unsigned int index;
|
||||
struct page *page;
|
||||
@@ -247,19 +247,18 @@ static void finish_compressed_bio_read(struct compressed_bio *cb, struct bio *bi
|
||||
}
|
||||
|
||||
/* Do io completion on the original bio */
|
||||
if (cb->errors) {
|
||||
bio_io_error(cb->orig_bio);
|
||||
if (cb->status != BLK_STS_OK) {
|
||||
cb->orig_bio->bi_status = cb->status;
|
||||
bio_endio(cb->orig_bio);
|
||||
} else {
|
||||
struct bio_vec *bvec;
|
||||
struct bvec_iter_all iter_all;
|
||||
|
||||
ASSERT(bio);
|
||||
ASSERT(!bio->bi_status);
|
||||
/*
|
||||
* We have verified the checksum already, set page checked so
|
||||
* the end_io handlers know about it
|
||||
*/
|
||||
ASSERT(!bio_flagged(bio, BIO_CLONED));
|
||||
ASSERT(!bio_flagged(cb->orig_bio, BIO_CLONED));
|
||||
bio_for_each_segment_all(bvec, cb->orig_bio, iter_all) {
|
||||
u64 bvec_start = page_offset(bvec->bv_page) +
|
||||
bvec->bv_offset;
|
||||
@@ -308,7 +307,7 @@ static void end_compressed_bio_read(struct bio *bio)
|
||||
* Some IO in this cb have failed, just skip checksum as there
|
||||
* is no way it could be correct.
|
||||
*/
|
||||
if (cb->errors == 1)
|
||||
if (cb->status != BLK_STS_OK)
|
||||
goto csum_failed;
|
||||
|
||||
inode = cb->inode;
|
||||
@@ -324,8 +323,8 @@ static void end_compressed_bio_read(struct bio *bio)
|
||||
|
||||
csum_failed:
|
||||
if (ret)
|
||||
cb->errors = 1;
|
||||
finish_compressed_bio_read(cb, bio);
|
||||
cb->status = errno_to_blk_status(ret);
|
||||
finish_compressed_bio_read(cb);
|
||||
out:
|
||||
bio_put(bio);
|
||||
}
|
||||
@@ -342,11 +341,12 @@ static noinline void end_compressed_writeback(struct inode *inode,
|
||||
unsigned long end_index = (cb->start + cb->len - 1) >> PAGE_SHIFT;
|
||||
struct page *pages[16];
|
||||
unsigned long nr_pages = end_index - index + 1;
|
||||
const int errno = blk_status_to_errno(cb->status);
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (cb->errors)
|
||||
mapping_set_error(inode->i_mapping, -EIO);
|
||||
if (errno)
|
||||
mapping_set_error(inode->i_mapping, errno);
|
||||
|
||||
while (nr_pages > 0) {
|
||||
ret = find_get_pages_contig(inode->i_mapping, index,
|
||||
@@ -358,7 +358,7 @@ static noinline void end_compressed_writeback(struct inode *inode,
|
||||
continue;
|
||||
}
|
||||
for (i = 0; i < ret; i++) {
|
||||
if (cb->errors)
|
||||
if (errno)
|
||||
SetPageError(pages[i]);
|
||||
btrfs_page_clamp_clear_writeback(fs_info, pages[i],
|
||||
cb->start, cb->len);
|
||||
@@ -381,9 +381,10 @@ static void finish_compressed_bio_write(struct compressed_bio *cb)
|
||||
*/
|
||||
btrfs_writepage_endio_finish_ordered(BTRFS_I(inode), NULL,
|
||||
cb->start, cb->start + cb->len - 1,
|
||||
!cb->errors);
|
||||
cb->status == BLK_STS_OK);
|
||||
|
||||
end_compressed_writeback(inode, cb);
|
||||
if (cb->writeback)
|
||||
end_compressed_writeback(inode, cb);
|
||||
/* Note, our inode could be gone now */
|
||||
|
||||
/*
|
||||
@@ -506,7 +507,8 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
|
||||
struct page **compressed_pages,
|
||||
unsigned int nr_pages,
|
||||
unsigned int write_flags,
|
||||
struct cgroup_subsys_state *blkcg_css)
|
||||
struct cgroup_subsys_state *blkcg_css,
|
||||
bool writeback)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = inode->root->fs_info;
|
||||
struct bio *bio = NULL;
|
||||
@@ -524,13 +526,14 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
|
||||
if (!cb)
|
||||
return BLK_STS_RESOURCE;
|
||||
refcount_set(&cb->pending_sectors, compressed_len >> fs_info->sectorsize_bits);
|
||||
cb->errors = 0;
|
||||
cb->status = BLK_STS_OK;
|
||||
cb->inode = &inode->vfs_inode;
|
||||
cb->start = start;
|
||||
cb->len = len;
|
||||
cb->mirror_num = 0;
|
||||
cb->compressed_pages = compressed_pages;
|
||||
cb->compressed_len = compressed_len;
|
||||
cb->writeback = writeback;
|
||||
cb->orig_bio = NULL;
|
||||
cb->nr_pages = nr_pages;
|
||||
|
||||
@@ -591,7 +594,7 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
|
||||
|
||||
if (submit) {
|
||||
if (!skip_sum) {
|
||||
ret = btrfs_csum_one_bio(inode, bio, start, 1);
|
||||
ret = btrfs_csum_one_bio(inode, bio, start, true);
|
||||
if (ret)
|
||||
goto finish_cb;
|
||||
}
|
||||
@@ -808,7 +811,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
|
||||
u64 em_len;
|
||||
u64 em_start;
|
||||
struct extent_map *em;
|
||||
blk_status_t ret = BLK_STS_RESOURCE;
|
||||
blk_status_t ret;
|
||||
int faili = 0;
|
||||
u8 *sums;
|
||||
|
||||
@@ -821,17 +824,21 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
|
||||
read_lock(&em_tree->lock);
|
||||
em = lookup_extent_mapping(em_tree, file_offset, fs_info->sectorsize);
|
||||
read_unlock(&em_tree->lock);
|
||||
if (!em)
|
||||
return BLK_STS_IOERR;
|
||||
if (!em) {
|
||||
ret = BLK_STS_IOERR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ASSERT(em->compress_type != BTRFS_COMPRESS_NONE);
|
||||
compressed_len = em->block_len;
|
||||
cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS);
|
||||
if (!cb)
|
||||
if (!cb) {
|
||||
ret = BLK_STS_RESOURCE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
refcount_set(&cb->pending_sectors, compressed_len >> fs_info->sectorsize_bits);
|
||||
cb->errors = 0;
|
||||
cb->status = BLK_STS_OK;
|
||||
cb->inode = inode;
|
||||
cb->mirror_num = mirror_num;
|
||||
sums = cb->sums;
|
||||
@@ -851,8 +858,10 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
|
||||
nr_pages = DIV_ROUND_UP(compressed_len, PAGE_SIZE);
|
||||
cb->compressed_pages = kcalloc(nr_pages, sizeof(struct page *),
|
||||
GFP_NOFS);
|
||||
if (!cb->compressed_pages)
|
||||
if (!cb->compressed_pages) {
|
||||
ret = BLK_STS_RESOURCE;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
for (pg_index = 0; pg_index < nr_pages; pg_index++) {
|
||||
cb->compressed_pages[pg_index] = alloc_page(GFP_NOFS);
|
||||
@@ -938,7 +947,7 @@ blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
|
||||
comp_bio = NULL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return BLK_STS_OK;
|
||||
|
||||
fail2:
|
||||
while (faili >= 0) {
|
||||
@@ -951,6 +960,8 @@ fail1:
|
||||
kfree(cb);
|
||||
out:
|
||||
free_extent_map(em);
|
||||
bio->bi_status = ret;
|
||||
bio_endio(bio);
|
||||
return ret;
|
||||
finish_cb:
|
||||
if (comp_bio) {
|
||||
@@ -970,7 +981,7 @@ finish_cb:
|
||||
*/
|
||||
ASSERT(refcount_read(&cb->pending_sectors));
|
||||
/* Now we are the only one referring @cb, can finish it safely. */
|
||||
finish_compressed_bio_read(cb, NULL);
|
||||
finish_compressed_bio_read(cb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ struct btrfs_inode;
|
||||
|
||||
/* Maximum length of compressed data stored on disk */
|
||||
#define BTRFS_MAX_COMPRESSED (SZ_128K)
|
||||
static_assert((BTRFS_MAX_COMPRESSED % PAGE_SIZE) == 0);
|
||||
|
||||
/* Maximum size of data before compression */
|
||||
#define BTRFS_MAX_UNCOMPRESSED (SZ_128K)
|
||||
|
||||
@@ -52,8 +54,11 @@ struct compressed_bio {
|
||||
/* The compression algorithm for this bio */
|
||||
u8 compress_type;
|
||||
|
||||
/* Whether this is a write for writeback. */
|
||||
bool writeback;
|
||||
|
||||
/* IO errors */
|
||||
u8 errors;
|
||||
blk_status_t status;
|
||||
int mirror_num;
|
||||
|
||||
/* for reads, this is the bio we are copying the data into */
|
||||
@@ -95,7 +100,8 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
|
||||
struct page **compressed_pages,
|
||||
unsigned int nr_pages,
|
||||
unsigned int write_flags,
|
||||
struct cgroup_subsys_state *blkcg_css);
|
||||
struct cgroup_subsys_state *blkcg_css,
|
||||
bool writeback);
|
||||
blk_status_t btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
|
||||
int mirror_num, unsigned long bio_flags);
|
||||
|
||||
|
||||
+61
-47
@@ -846,9 +846,11 @@ struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent,
|
||||
btrfs_header_owner(parent),
|
||||
btrfs_node_ptr_generation(parent, slot),
|
||||
level - 1, &first_key);
|
||||
if (!IS_ERR(eb) && !extent_buffer_uptodate(eb)) {
|
||||
if (IS_ERR(eb))
|
||||
return eb;
|
||||
if (!extent_buffer_uptodate(eb)) {
|
||||
free_extent_buffer(eb);
|
||||
eb = ERR_PTR(-EIO);
|
||||
return ERR_PTR(-EIO);
|
||||
}
|
||||
|
||||
return eb;
|
||||
@@ -1436,13 +1438,13 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
|
||||
|
||||
/* now we're allowed to do a blocking uptodate check */
|
||||
ret = btrfs_read_buffer(tmp, gen, parent_level - 1, &first_key);
|
||||
if (!ret) {
|
||||
*eb_ret = tmp;
|
||||
return 0;
|
||||
if (ret) {
|
||||
free_extent_buffer(tmp);
|
||||
btrfs_release_path(p);
|
||||
return -EIO;
|
||||
}
|
||||
free_extent_buffer(tmp);
|
||||
btrfs_release_path(p);
|
||||
return -EIO;
|
||||
*eb_ret = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1460,19 +1462,19 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
|
||||
ret = -EAGAIN;
|
||||
tmp = read_tree_block(fs_info, blocknr, root->root_key.objectid,
|
||||
gen, parent_level - 1, &first_key);
|
||||
if (!IS_ERR(tmp)) {
|
||||
/*
|
||||
* If the read above didn't mark this buffer up to date,
|
||||
* it will never end up being up to date. Set ret to EIO now
|
||||
* and give up so that our caller doesn't loop forever
|
||||
* on our EAGAINs.
|
||||
*/
|
||||
if (!extent_buffer_uptodate(tmp))
|
||||
ret = -EIO;
|
||||
free_extent_buffer(tmp);
|
||||
} else {
|
||||
ret = PTR_ERR(tmp);
|
||||
if (IS_ERR(tmp)) {
|
||||
btrfs_release_path(p);
|
||||
return PTR_ERR(tmp);
|
||||
}
|
||||
/*
|
||||
* If the read above didn't mark this buffer up to date,
|
||||
* it will never end up being up to date. Set ret to EIO now
|
||||
* and give up so that our caller doesn't loop forever
|
||||
* on our EAGAINs.
|
||||
*/
|
||||
if (!extent_buffer_uptodate(tmp))
|
||||
ret = -EIO;
|
||||
free_extent_buffer(tmp);
|
||||
|
||||
btrfs_release_path(p);
|
||||
return ret;
|
||||
@@ -2990,16 +2992,11 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
if (free_space < data_size)
|
||||
goto out_unlock;
|
||||
|
||||
/* cow and double check */
|
||||
ret = btrfs_cow_block(trans, root, right, upper,
|
||||
slot + 1, &right, BTRFS_NESTING_RIGHT_COW);
|
||||
if (ret)
|
||||
goto out_unlock;
|
||||
|
||||
free_space = btrfs_leaf_free_space(right);
|
||||
if (free_space < data_size)
|
||||
goto out_unlock;
|
||||
|
||||
left_nritems = btrfs_header_nritems(left);
|
||||
if (left_nritems == 0)
|
||||
goto out_unlock;
|
||||
@@ -3224,7 +3221,6 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* cow and double check */
|
||||
ret = btrfs_cow_block(trans, root, left,
|
||||
path->nodes[1], slot - 1, &left,
|
||||
BTRFS_NESTING_LEFT_COW);
|
||||
@@ -3235,12 +3231,6 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
goto out;
|
||||
}
|
||||
|
||||
free_space = btrfs_leaf_free_space(left);
|
||||
if (free_space < data_size) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (check_sibling_keys(left, right)) {
|
||||
ret = -EUCLEAN;
|
||||
goto out;
|
||||
@@ -4170,24 +4160,22 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
struct extent_buffer *leaf;
|
||||
u32 last_off;
|
||||
u32 dsize = 0;
|
||||
int ret = 0;
|
||||
int wret;
|
||||
int i;
|
||||
u32 nritems;
|
||||
|
||||
leaf = path->nodes[0];
|
||||
last_off = btrfs_item_offset(leaf, slot + nr - 1);
|
||||
|
||||
for (i = 0; i < nr; i++)
|
||||
dsize += btrfs_item_size(leaf, slot + i);
|
||||
|
||||
nritems = btrfs_header_nritems(leaf);
|
||||
|
||||
if (slot + nr != nritems) {
|
||||
int data_end = leaf_data_end(leaf);
|
||||
const u32 last_off = btrfs_item_offset(leaf, slot + nr - 1);
|
||||
const int data_end = leaf_data_end(leaf);
|
||||
struct btrfs_map_token token;
|
||||
u32 dsize = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nr; i++)
|
||||
dsize += btrfs_item_size(leaf, slot + i);
|
||||
|
||||
memmove_extent_buffer(leaf, BTRFS_LEAF_DATA_OFFSET +
|
||||
data_end + dsize,
|
||||
@@ -4227,24 +4215,50 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
fixup_low_keys(path, &disk_key, 1);
|
||||
}
|
||||
|
||||
/* delete the leaf if it is mostly empty */
|
||||
/*
|
||||
* Try to delete the leaf if it is mostly empty. We do this by
|
||||
* trying to move all its items into its left and right neighbours.
|
||||
* If we can't move all the items, then we don't delete it - it's
|
||||
* not ideal, but future insertions might fill the leaf with more
|
||||
* items, or items from other leaves might be moved later into our
|
||||
* leaf due to deletions on those leaves.
|
||||
*/
|
||||
if (used < BTRFS_LEAF_DATA_SIZE(fs_info) / 3) {
|
||||
u32 min_push_space;
|
||||
|
||||
/* push_leaf_left fixes the path.
|
||||
* make sure the path still points to our leaf
|
||||
* for possible call to del_ptr below
|
||||
*/
|
||||
slot = path->slots[1];
|
||||
atomic_inc(&leaf->refs);
|
||||
|
||||
wret = push_leaf_left(trans, root, path, 1, 1,
|
||||
1, (u32)-1);
|
||||
/*
|
||||
* We want to be able to at least push one item to the
|
||||
* left neighbour leaf, and that's the first item.
|
||||
*/
|
||||
min_push_space = sizeof(struct btrfs_item) +
|
||||
btrfs_item_size(leaf, 0);
|
||||
wret = push_leaf_left(trans, root, path, 0,
|
||||
min_push_space, 1, (u32)-1);
|
||||
if (wret < 0 && wret != -ENOSPC)
|
||||
ret = wret;
|
||||
|
||||
if (path->nodes[0] == leaf &&
|
||||
btrfs_header_nritems(leaf)) {
|
||||
wret = push_leaf_right(trans, root, path, 1,
|
||||
1, 1, 0);
|
||||
/*
|
||||
* If we were not able to push all items from our
|
||||
* leaf to its left neighbour, then attempt to
|
||||
* either push all the remaining items to the
|
||||
* right neighbour or none. There's no advantage
|
||||
* in pushing only some items, instead of all, as
|
||||
* it's pointless to end up with a leaf having
|
||||
* too few items while the neighbours can be full
|
||||
* or nearly full.
|
||||
*/
|
||||
nritems = btrfs_header_nritems(leaf);
|
||||
min_push_space = leaf_space_used(leaf, 0, nritems);
|
||||
wret = push_leaf_right(trans, root, path, 0,
|
||||
min_push_space, 1, 0);
|
||||
if (wret < 0 && wret != -ENOSPC)
|
||||
ret = wret;
|
||||
}
|
||||
|
||||
+71
-12
@@ -49,6 +49,7 @@ extern struct kmem_cache *btrfs_free_space_bitmap_cachep;
|
||||
struct btrfs_ordered_sum;
|
||||
struct btrfs_ref;
|
||||
struct btrfs_bio;
|
||||
struct btrfs_ioctl_encoded_io_args;
|
||||
|
||||
#define BTRFS_MAGIC 0x4D5F53665248425FULL /* ascii _BHRfS_M, no null */
|
||||
|
||||
@@ -148,6 +149,8 @@ enum {
|
||||
|
||||
/* Indicates there was an error cleaning up a log tree. */
|
||||
BTRFS_FS_STATE_LOG_CLEANUP_ERROR,
|
||||
|
||||
BTRFS_FS_STATE_COUNT
|
||||
};
|
||||
|
||||
#define BTRFS_BACKREF_REV_MAX 256
|
||||
@@ -274,8 +277,14 @@ struct btrfs_super_block {
|
||||
/* the UUID written into btree blocks */
|
||||
u8 metadata_uuid[BTRFS_FSID_SIZE];
|
||||
|
||||
/* Extent tree v2 */
|
||||
__le64 block_group_root;
|
||||
__le64 block_group_root_generation;
|
||||
u8 block_group_root_level;
|
||||
|
||||
/* future expansion */
|
||||
__le64 reserved[28];
|
||||
u8 reserved8[7];
|
||||
__le64 reserved[25];
|
||||
u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
|
||||
struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS];
|
||||
|
||||
@@ -300,6 +309,26 @@ static_assert(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
|
||||
#define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL
|
||||
#define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL
|
||||
|
||||
#ifdef CONFIG_BTRFS_DEBUG
|
||||
/*
|
||||
* Extent tree v2 supported only with CONFIG_BTRFS_DEBUG
|
||||
*/
|
||||
#define BTRFS_FEATURE_INCOMPAT_SUPP \
|
||||
(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \
|
||||
BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \
|
||||
BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS | \
|
||||
BTRFS_FEATURE_INCOMPAT_BIG_METADATA | \
|
||||
BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO | \
|
||||
BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD | \
|
||||
BTRFS_FEATURE_INCOMPAT_RAID56 | \
|
||||
BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF | \
|
||||
BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA | \
|
||||
BTRFS_FEATURE_INCOMPAT_NO_HOLES | \
|
||||
BTRFS_FEATURE_INCOMPAT_METADATA_UUID | \
|
||||
BTRFS_FEATURE_INCOMPAT_RAID1C34 | \
|
||||
BTRFS_FEATURE_INCOMPAT_ZONED | \
|
||||
BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2)
|
||||
#else
|
||||
#define BTRFS_FEATURE_INCOMPAT_SUPP \
|
||||
(BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF | \
|
||||
BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL | \
|
||||
@@ -314,6 +343,7 @@ static_assert(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
|
||||
BTRFS_FEATURE_INCOMPAT_METADATA_UUID | \
|
||||
BTRFS_FEATURE_INCOMPAT_RAID1C34 | \
|
||||
BTRFS_FEATURE_INCOMPAT_ZONED)
|
||||
#endif
|
||||
|
||||
#define BTRFS_FEATURE_INCOMPAT_SAFE_SET \
|
||||
(BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF)
|
||||
@@ -636,6 +666,7 @@ struct btrfs_fs_info {
|
||||
struct btrfs_root *quota_root;
|
||||
struct btrfs_root *uuid_root;
|
||||
struct btrfs_root *data_reloc_root;
|
||||
struct btrfs_root *block_group_root;
|
||||
|
||||
/* the log root tree is a directory of all the other log roots */
|
||||
struct btrfs_root *log_root_tree;
|
||||
@@ -1030,6 +1061,8 @@ struct btrfs_fs_info {
|
||||
spinlock_t relocation_bg_lock;
|
||||
u64 data_reloc_bg;
|
||||
|
||||
u64 nr_global_roots;
|
||||
|
||||
spinlock_t zone_active_bgs_lock;
|
||||
struct list_head zone_active_bgs;
|
||||
|
||||
@@ -1609,25 +1642,25 @@ DECLARE_BTRFS_SETGET_BITS(64)
|
||||
static inline u##bits btrfs_##name(const struct extent_buffer *eb, \
|
||||
const type *s) \
|
||||
{ \
|
||||
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
|
||||
static_assert(sizeof(u##bits) == sizeof(((type *)0))->member); \
|
||||
return btrfs_get_##bits(eb, s, offsetof(type, member)); \
|
||||
} \
|
||||
static inline void btrfs_set_##name(const struct extent_buffer *eb, type *s, \
|
||||
u##bits val) \
|
||||
{ \
|
||||
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
|
||||
static_assert(sizeof(u##bits) == sizeof(((type *)0))->member); \
|
||||
btrfs_set_##bits(eb, s, offsetof(type, member), val); \
|
||||
} \
|
||||
static inline u##bits btrfs_token_##name(struct btrfs_map_token *token, \
|
||||
const type *s) \
|
||||
{ \
|
||||
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
|
||||
static_assert(sizeof(u##bits) == sizeof(((type *)0))->member); \
|
||||
return btrfs_get_token_##bits(token, s, offsetof(type, member));\
|
||||
} \
|
||||
static inline void btrfs_set_token_##name(struct btrfs_map_token *token,\
|
||||
type *s, u##bits val) \
|
||||
{ \
|
||||
BUILD_BUG_ON(sizeof(u##bits) != sizeof(((type *)0))->member); \
|
||||
static_assert(sizeof(u##bits) == sizeof(((type *)0))->member); \
|
||||
btrfs_set_token_##bits(token, s, offsetof(type, member), val); \
|
||||
}
|
||||
|
||||
@@ -1658,8 +1691,8 @@ static inline void btrfs_set_##name(type *s, u##bits val) \
|
||||
static inline u64 btrfs_device_total_bytes(const struct extent_buffer *eb,
|
||||
struct btrfs_dev_item *s)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(u64) !=
|
||||
sizeof(((struct btrfs_dev_item *)0))->total_bytes);
|
||||
static_assert(sizeof(u64) ==
|
||||
sizeof(((struct btrfs_dev_item *)0))->total_bytes);
|
||||
return btrfs_get_64(eb, s, offsetof(struct btrfs_dev_item,
|
||||
total_bytes));
|
||||
}
|
||||
@@ -1667,8 +1700,8 @@ static inline void btrfs_set_device_total_bytes(const struct extent_buffer *eb,
|
||||
struct btrfs_dev_item *s,
|
||||
u64 val)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(u64) !=
|
||||
sizeof(((struct btrfs_dev_item *)0))->total_bytes);
|
||||
static_assert(sizeof(u64) ==
|
||||
sizeof(((struct btrfs_dev_item *)0))->total_bytes);
|
||||
WARN_ON(!IS_ALIGNED(val, eb->fs_info->sectorsize));
|
||||
btrfs_set_64(eb, s, offsetof(struct btrfs_dev_item, total_bytes), val);
|
||||
}
|
||||
@@ -2328,6 +2361,17 @@ BTRFS_SETGET_STACK_FUNCS(backup_bytes_used, struct btrfs_root_backup,
|
||||
BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup,
|
||||
num_devices, 64);
|
||||
|
||||
/*
|
||||
* For extent tree v2 we overload the extent root with the block group root, as
|
||||
* we will have multiple extent roots.
|
||||
*/
|
||||
BTRFS_SETGET_STACK_FUNCS(backup_block_group_root, struct btrfs_root_backup,
|
||||
extent_root, 64);
|
||||
BTRFS_SETGET_STACK_FUNCS(backup_block_group_root_gen, struct btrfs_root_backup,
|
||||
extent_root_gen, 64);
|
||||
BTRFS_SETGET_STACK_FUNCS(backup_block_group_root_level,
|
||||
struct btrfs_root_backup, extent_root_level, 8);
|
||||
|
||||
/* struct btrfs_balance_item */
|
||||
BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64);
|
||||
|
||||
@@ -2462,6 +2506,13 @@ BTRFS_SETGET_STACK_FUNCS(super_cache_generation, struct btrfs_super_block,
|
||||
BTRFS_SETGET_STACK_FUNCS(super_magic, struct btrfs_super_block, magic, 64);
|
||||
BTRFS_SETGET_STACK_FUNCS(super_uuid_tree_generation, struct btrfs_super_block,
|
||||
uuid_tree_generation, 64);
|
||||
BTRFS_SETGET_STACK_FUNCS(super_block_group_root, struct btrfs_super_block,
|
||||
block_group_root, 64);
|
||||
BTRFS_SETGET_STACK_FUNCS(super_block_group_root_generation,
|
||||
struct btrfs_super_block,
|
||||
block_group_root_generation, 64);
|
||||
BTRFS_SETGET_STACK_FUNCS(super_block_group_root_level, struct btrfs_super_block,
|
||||
block_group_root_level, 8);
|
||||
|
||||
int btrfs_super_csum_size(const struct btrfs_super_block *s);
|
||||
const char *btrfs_super_csum_name(u16 csum_type);
|
||||
@@ -2839,7 +2890,8 @@ void btrfs_subvolume_release_metadata(struct btrfs_root *root,
|
||||
struct btrfs_block_rsv *rsv);
|
||||
void btrfs_delalloc_release_extents(struct btrfs_inode *inode, u64 num_bytes);
|
||||
|
||||
int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes);
|
||||
int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
|
||||
u64 disk_num_bytes);
|
||||
u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo);
|
||||
int btrfs_error_unpin_extent_range(struct btrfs_fs_info *fs_info,
|
||||
u64 start, u64 end);
|
||||
@@ -3155,7 +3207,7 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct btrfs_ordered_sum *sums);
|
||||
blk_status_t btrfs_csum_one_bio(struct btrfs_inode *inode, struct bio *bio,
|
||||
u64 file_start, int contig);
|
||||
u64 offset, bool one_ordered);
|
||||
int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
|
||||
struct list_head *list, int search_commit);
|
||||
void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode,
|
||||
@@ -3256,6 +3308,11 @@ int btrfs_writepage_cow_fixup(struct page *page);
|
||||
void btrfs_writepage_endio_finish_ordered(struct btrfs_inode *inode,
|
||||
struct page *page, u64 start,
|
||||
u64 end, bool uptodate);
|
||||
ssize_t btrfs_encoded_read(struct kiocb *iocb, struct iov_iter *iter,
|
||||
struct btrfs_ioctl_encoded_io_args *encoded);
|
||||
ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
|
||||
const struct btrfs_ioctl_encoded_io_args *encoded);
|
||||
|
||||
extern const struct dentry_operations btrfs_dentry_operations;
|
||||
extern const struct iomap_ops btrfs_dio_iomap_ops;
|
||||
extern const struct iomap_dio_ops btrfs_dio_ops;
|
||||
@@ -3318,6 +3375,8 @@ int btrfs_replace_file_extents(struct btrfs_inode *inode,
|
||||
struct btrfs_trans_handle **trans_out);
|
||||
int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_inode *inode, u64 start, u64 end);
|
||||
ssize_t btrfs_do_write_iter(struct kiocb *iocb, struct iov_iter *from,
|
||||
const struct btrfs_ioctl_encoded_io_args *encoded);
|
||||
int btrfs_release_file(struct inode *inode, struct file *file);
|
||||
int btrfs_dirty_pages(struct btrfs_inode *inode, struct page **pages,
|
||||
size_t num_pages, loff_t pos, size_t write_bytes,
|
||||
@@ -3774,7 +3833,7 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root);
|
||||
int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root);
|
||||
int btrfs_recover_relocation(struct btrfs_root *root);
|
||||
int btrfs_recover_relocation(struct btrfs_fs_info *fs_info);
|
||||
int btrfs_reloc_clone_csums(struct btrfs_inode *inode, u64 file_pos, u64 len);
|
||||
int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, struct extent_buffer *buf,
|
||||
|
||||
@@ -270,11 +270,11 @@ static void btrfs_calculate_inode_block_rsv_size(struct btrfs_fs_info *fs_info,
|
||||
}
|
||||
|
||||
static void calc_inode_reservations(struct btrfs_fs_info *fs_info,
|
||||
u64 num_bytes, u64 *meta_reserve,
|
||||
u64 *qgroup_reserve)
|
||||
u64 num_bytes, u64 disk_num_bytes,
|
||||
u64 *meta_reserve, u64 *qgroup_reserve)
|
||||
{
|
||||
u64 nr_extents = count_max_extents(num_bytes);
|
||||
u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, num_bytes);
|
||||
u64 csum_leaves = btrfs_csum_bytes_to_leaves(fs_info, disk_num_bytes);
|
||||
u64 inode_update = btrfs_calc_metadata_size(fs_info, 1);
|
||||
|
||||
*meta_reserve = btrfs_calc_insert_metadata_size(fs_info,
|
||||
@@ -288,7 +288,8 @@ static void calc_inode_reservations(struct btrfs_fs_info *fs_info,
|
||||
*qgroup_reserve = nr_extents * fs_info->nodesize;
|
||||
}
|
||||
|
||||
int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes)
|
||||
int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes,
|
||||
u64 disk_num_bytes)
|
||||
{
|
||||
struct btrfs_root *root = inode->root;
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
@@ -318,6 +319,7 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes)
|
||||
}
|
||||
|
||||
num_bytes = ALIGN(num_bytes, fs_info->sectorsize);
|
||||
disk_num_bytes = ALIGN(disk_num_bytes, fs_info->sectorsize);
|
||||
|
||||
/*
|
||||
* We always want to do it this way, every other way is wrong and ends
|
||||
@@ -329,8 +331,8 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes)
|
||||
* everything out and try again, which is bad. This way we just
|
||||
* over-reserve slightly, and clean up the mess when we are done.
|
||||
*/
|
||||
calc_inode_reservations(fs_info, num_bytes, &meta_reserve,
|
||||
&qgroup_reserve);
|
||||
calc_inode_reservations(fs_info, num_bytes, disk_num_bytes,
|
||||
&meta_reserve, &qgroup_reserve);
|
||||
ret = btrfs_qgroup_reserve_meta_prealloc(root, qgroup_reserve, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -349,7 +351,7 @@ int btrfs_delalloc_reserve_metadata(struct btrfs_inode *inode, u64 num_bytes)
|
||||
spin_lock(&inode->lock);
|
||||
nr_extents = count_max_extents(num_bytes);
|
||||
btrfs_mod_outstanding_extents(inode, nr_extents);
|
||||
inode->csum_bytes += num_bytes;
|
||||
inode->csum_bytes += disk_num_bytes;
|
||||
btrfs_calculate_inode_block_rsv_size(fs_info, inode);
|
||||
spin_unlock(&inode->lock);
|
||||
|
||||
@@ -454,7 +456,7 @@ int btrfs_delalloc_reserve_space(struct btrfs_inode *inode,
|
||||
ret = btrfs_check_data_free_space(inode, reserved, start, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ret = btrfs_delalloc_reserve_metadata(inode, len);
|
||||
ret = btrfs_delalloc_reserve_metadata(inode, len, len);
|
||||
if (ret < 0) {
|
||||
btrfs_free_reserved_data_space(inode, *reserved, start, len);
|
||||
extent_changeset_free(*reserved);
|
||||
|
||||
+11
-7
@@ -243,6 +243,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_device *srcdev,
|
||||
struct btrfs_device **device_out)
|
||||
{
|
||||
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
|
||||
struct btrfs_device *device;
|
||||
struct block_device *bdev;
|
||||
struct rcu_string *name;
|
||||
@@ -271,7 +272,7 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
|
||||
|
||||
sync_blockdev(bdev);
|
||||
|
||||
list_for_each_entry(device, &fs_info->fs_devices->devices, dev_list) {
|
||||
list_for_each_entry(device, &fs_devices->devices, dev_list) {
|
||||
if (device->bdev == bdev) {
|
||||
btrfs_err(fs_info,
|
||||
"target device is in the filesystem!");
|
||||
@@ -302,6 +303,9 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
|
||||
goto error;
|
||||
}
|
||||
rcu_assign_pointer(device->name, name);
|
||||
ret = lookup_bdev(device_path, &device->devt);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
set_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
|
||||
device->generation = 0;
|
||||
@@ -320,17 +324,17 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
|
||||
device->mode = FMODE_EXCL;
|
||||
device->dev_stats_valid = 1;
|
||||
set_blocksize(device->bdev, BTRFS_BDEV_BLOCKSIZE);
|
||||
device->fs_devices = fs_info->fs_devices;
|
||||
device->fs_devices = fs_devices;
|
||||
|
||||
ret = btrfs_get_dev_zone_info(device, false);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
mutex_lock(&fs_info->fs_devices->device_list_mutex);
|
||||
list_add(&device->dev_list, &fs_info->fs_devices->devices);
|
||||
fs_info->fs_devices->num_devices++;
|
||||
fs_info->fs_devices->open_devices++;
|
||||
mutex_unlock(&fs_info->fs_devices->device_list_mutex);
|
||||
mutex_lock(&fs_devices->device_list_mutex);
|
||||
list_add(&device->dev_list, &fs_devices->devices);
|
||||
fs_devices->num_devices++;
|
||||
fs_devices->open_devices++;
|
||||
mutex_unlock(&fs_devices->device_list_mutex);
|
||||
|
||||
*device_out = device;
|
||||
return 0;
|
||||
|
||||
+156
-63
@@ -441,17 +441,31 @@ static int csum_one_extent_buffer(struct extent_buffer *eb)
|
||||
else
|
||||
ret = btrfs_check_leaf_full(eb);
|
||||
|
||||
if (ret < 0) {
|
||||
btrfs_print_tree(eb, 0);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* Also check the generation, the eb reached here must be newer than
|
||||
* last committed. Or something seriously wrong happened.
|
||||
*/
|
||||
if (unlikely(btrfs_header_generation(eb) <= fs_info->last_trans_committed)) {
|
||||
ret = -EUCLEAN;
|
||||
btrfs_err(fs_info,
|
||||
"block=%llu write time tree block corruption detected",
|
||||
eb->start);
|
||||
WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
|
||||
return ret;
|
||||
"block=%llu bad generation, have %llu expect > %llu",
|
||||
eb->start, btrfs_header_generation(eb),
|
||||
fs_info->last_trans_committed);
|
||||
goto error;
|
||||
}
|
||||
write_extent_buffer(eb, result, 0, fs_info->csum_size);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
btrfs_print_tree(eb, 0);
|
||||
btrfs_err(fs_info, "block=%llu write time tree block corruption detected",
|
||||
eb->start);
|
||||
WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Checksum all dirty extent buffers in one bio_vec */
|
||||
@@ -1289,12 +1303,33 @@ struct btrfs_root *btrfs_global_root(struct btrfs_fs_info *fs_info,
|
||||
return root;
|
||||
}
|
||||
|
||||
static u64 btrfs_global_root_id(struct btrfs_fs_info *fs_info, u64 bytenr)
|
||||
{
|
||||
struct btrfs_block_group *block_group;
|
||||
u64 ret;
|
||||
|
||||
if (!btrfs_fs_incompat(fs_info, EXTENT_TREE_V2))
|
||||
return 0;
|
||||
|
||||
if (bytenr)
|
||||
block_group = btrfs_lookup_block_group(fs_info, bytenr);
|
||||
else
|
||||
block_group = btrfs_lookup_first_block_group(fs_info, bytenr);
|
||||
ASSERT(block_group);
|
||||
if (!block_group)
|
||||
return 0;
|
||||
ret = block_group->global_root_id;
|
||||
btrfs_put_block_group(block_group);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct btrfs_root *btrfs_csum_root(struct btrfs_fs_info *fs_info, u64 bytenr)
|
||||
{
|
||||
struct btrfs_key key = {
|
||||
.objectid = BTRFS_CSUM_TREE_OBJECTID,
|
||||
.type = BTRFS_ROOT_ITEM_KEY,
|
||||
.offset = 0,
|
||||
.offset = btrfs_global_root_id(fs_info, bytenr),
|
||||
};
|
||||
|
||||
return btrfs_global_root(fs_info, &key);
|
||||
@@ -1305,7 +1340,7 @@ struct btrfs_root *btrfs_extent_root(struct btrfs_fs_info *fs_info, u64 bytenr)
|
||||
struct btrfs_key key = {
|
||||
.objectid = BTRFS_EXTENT_TREE_OBJECTID,
|
||||
.type = BTRFS_ROOT_ITEM_KEY,
|
||||
.offset = 0,
|
||||
.offset = btrfs_global_root_id(fs_info, bytenr),
|
||||
};
|
||||
|
||||
return btrfs_global_root(fs_info, &key);
|
||||
@@ -1522,7 +1557,8 @@ static struct btrfs_root *read_tree_root_path(struct btrfs_root *tree_root,
|
||||
ret = PTR_ERR(root->node);
|
||||
root->node = NULL;
|
||||
goto fail;
|
||||
} else if (!btrfs_buffer_uptodate(root->node, generation, 0)) {
|
||||
}
|
||||
if (!btrfs_buffer_uptodate(root->node, generation, 0)) {
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
@@ -1727,6 +1763,7 @@ void btrfs_free_fs_info(struct btrfs_fs_info *fs_info)
|
||||
btrfs_put_root(fs_info->uuid_root);
|
||||
btrfs_put_root(fs_info->fs_root);
|
||||
btrfs_put_root(fs_info->data_reloc_root);
|
||||
btrfs_put_root(fs_info->block_group_root);
|
||||
btrfs_check_leaked_roots(fs_info);
|
||||
btrfs_extent_buffer_leak_debug_check(fs_info);
|
||||
kfree(fs_info->super_copy);
|
||||
@@ -1925,8 +1962,7 @@ static void end_workqueue_fn(struct btrfs_work *work)
|
||||
|
||||
static int cleaner_kthread(void *arg)
|
||||
{
|
||||
struct btrfs_root *root = arg;
|
||||
struct btrfs_fs_info *fs_info = root->fs_info;
|
||||
struct btrfs_fs_info *fs_info = (struct btrfs_fs_info *)arg;
|
||||
int again;
|
||||
|
||||
while (1) {
|
||||
@@ -1959,7 +1995,7 @@ static int cleaner_kthread(void *arg)
|
||||
|
||||
btrfs_run_delayed_iputs(fs_info);
|
||||
|
||||
again = btrfs_clean_one_deleted_snapshot(root);
|
||||
again = btrfs_clean_one_deleted_snapshot(fs_info);
|
||||
mutex_unlock(&fs_info->cleaner_mutex);
|
||||
|
||||
/*
|
||||
@@ -2095,8 +2131,6 @@ static void backup_super_roots(struct btrfs_fs_info *info)
|
||||
{
|
||||
const int next_backup = info->backup_root_index;
|
||||
struct btrfs_root_backup *root_backup;
|
||||
struct btrfs_root *extent_root = btrfs_extent_root(info, 0);
|
||||
struct btrfs_root *csum_root = btrfs_csum_root(info, 0);
|
||||
|
||||
root_backup = info->super_for_commit->super_roots + next_backup;
|
||||
|
||||
@@ -2121,11 +2155,30 @@ static void backup_super_roots(struct btrfs_fs_info *info)
|
||||
btrfs_set_backup_chunk_root_level(root_backup,
|
||||
btrfs_header_level(info->chunk_root->node));
|
||||
|
||||
btrfs_set_backup_extent_root(root_backup, extent_root->node->start);
|
||||
btrfs_set_backup_extent_root_gen(root_backup,
|
||||
btrfs_header_generation(extent_root->node));
|
||||
btrfs_set_backup_extent_root_level(root_backup,
|
||||
btrfs_header_level(extent_root->node));
|
||||
if (btrfs_fs_incompat(info, EXTENT_TREE_V2)) {
|
||||
btrfs_set_backup_block_group_root(root_backup,
|
||||
info->block_group_root->node->start);
|
||||
btrfs_set_backup_block_group_root_gen(root_backup,
|
||||
btrfs_header_generation(info->block_group_root->node));
|
||||
btrfs_set_backup_block_group_root_level(root_backup,
|
||||
btrfs_header_level(info->block_group_root->node));
|
||||
} else {
|
||||
struct btrfs_root *extent_root = btrfs_extent_root(info, 0);
|
||||
struct btrfs_root *csum_root = btrfs_csum_root(info, 0);
|
||||
|
||||
btrfs_set_backup_extent_root(root_backup,
|
||||
extent_root->node->start);
|
||||
btrfs_set_backup_extent_root_gen(root_backup,
|
||||
btrfs_header_generation(extent_root->node));
|
||||
btrfs_set_backup_extent_root_level(root_backup,
|
||||
btrfs_header_level(extent_root->node));
|
||||
|
||||
btrfs_set_backup_csum_root(root_backup, csum_root->node->start);
|
||||
btrfs_set_backup_csum_root_gen(root_backup,
|
||||
btrfs_header_generation(csum_root->node));
|
||||
btrfs_set_backup_csum_root_level(root_backup,
|
||||
btrfs_header_level(csum_root->node));
|
||||
}
|
||||
|
||||
/*
|
||||
* we might commit during log recovery, which happens before we set
|
||||
@@ -2146,12 +2199,6 @@ static void backup_super_roots(struct btrfs_fs_info *info)
|
||||
btrfs_set_backup_dev_root_level(root_backup,
|
||||
btrfs_header_level(info->dev_root->node));
|
||||
|
||||
btrfs_set_backup_csum_root(root_backup, csum_root->node->start);
|
||||
btrfs_set_backup_csum_root_gen(root_backup,
|
||||
btrfs_header_generation(csum_root->node));
|
||||
btrfs_set_backup_csum_root_level(root_backup,
|
||||
btrfs_header_level(csum_root->node));
|
||||
|
||||
btrfs_set_backup_total_bytes(root_backup,
|
||||
btrfs_super_total_bytes(info->super_copy));
|
||||
btrfs_set_backup_bytes_used(root_backup,
|
||||
@@ -2269,6 +2316,7 @@ static void free_root_pointers(struct btrfs_fs_info *info, bool free_chunk_root)
|
||||
free_root_extent_buffers(info->uuid_root);
|
||||
free_root_extent_buffers(info->fs_root);
|
||||
free_root_extent_buffers(info->data_reloc_root);
|
||||
free_root_extent_buffers(info->block_group_root);
|
||||
if (free_chunk_root)
|
||||
free_root_extent_buffers(info->chunk_root);
|
||||
}
|
||||
@@ -2504,11 +2552,13 @@ static int btrfs_replay_log(struct btrfs_fs_info *fs_info,
|
||||
log_tree_root->node = NULL;
|
||||
btrfs_put_root(log_tree_root);
|
||||
return ret;
|
||||
} else if (!extent_buffer_uptodate(log_tree_root->node)) {
|
||||
}
|
||||
if (!extent_buffer_uptodate(log_tree_root->node)) {
|
||||
btrfs_err(fs_info, "failed to read log tree");
|
||||
btrfs_put_root(log_tree_root);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* returns with log_tree_root freed on success */
|
||||
ret = btrfs_recover_log_trees(log_tree_root);
|
||||
if (ret) {
|
||||
@@ -2533,6 +2583,7 @@ static int load_global_roots_objectid(struct btrfs_root *tree_root,
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = tree_root->fs_info;
|
||||
struct btrfs_root *root;
|
||||
u64 max_global_id = 0;
|
||||
int ret;
|
||||
struct btrfs_key key = {
|
||||
.objectid = objectid,
|
||||
@@ -2568,6 +2619,13 @@ static int load_global_roots_objectid(struct btrfs_root *tree_root,
|
||||
break;
|
||||
btrfs_release_path(path);
|
||||
|
||||
/*
|
||||
* Just worry about this for extent tree, it'll be the same for
|
||||
* everybody.
|
||||
*/
|
||||
if (objectid == BTRFS_EXTENT_TREE_OBJECTID)
|
||||
max_global_id = max(max_global_id, key.offset);
|
||||
|
||||
found = true;
|
||||
root = read_tree_root_path(tree_root, path, &key);
|
||||
if (IS_ERR(root)) {
|
||||
@@ -2585,6 +2643,9 @@ static int load_global_roots_objectid(struct btrfs_root *tree_root,
|
||||
}
|
||||
btrfs_release_path(path);
|
||||
|
||||
if (objectid == BTRFS_EXTENT_TREE_OBJECTID)
|
||||
fs_info->nr_global_roots = max_global_id + 1;
|
||||
|
||||
if (!found || ret) {
|
||||
if (objectid == BTRFS_CSUM_TREE_OBJECTID)
|
||||
set_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state);
|
||||
@@ -2930,6 +2991,56 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int load_super_root(struct btrfs_root *root, u64 bytenr, u64 gen, int level)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
root->node = read_tree_block(root->fs_info, bytenr,
|
||||
root->root_key.objectid, gen, level, NULL);
|
||||
if (IS_ERR(root->node)) {
|
||||
ret = PTR_ERR(root->node);
|
||||
root->node = NULL;
|
||||
return ret;
|
||||
}
|
||||
if (!extent_buffer_uptodate(root->node)) {
|
||||
free_extent_buffer(root->node);
|
||||
root->node = NULL;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
btrfs_set_root_node(&root->root_item, root->node);
|
||||
root->commit_root = btrfs_root_node(root);
|
||||
btrfs_set_root_refs(&root->root_item, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int load_important_roots(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
struct btrfs_super_block *sb = fs_info->super_copy;
|
||||
u64 gen, bytenr;
|
||||
int level, ret;
|
||||
|
||||
bytenr = btrfs_super_root(sb);
|
||||
gen = btrfs_super_generation(sb);
|
||||
level = btrfs_super_root_level(sb);
|
||||
ret = load_super_root(fs_info->tree_root, bytenr, gen, level);
|
||||
if (ret) {
|
||||
btrfs_warn(fs_info, "couldn't read tree root");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!btrfs_fs_incompat(fs_info, EXTENT_TREE_V2))
|
||||
return 0;
|
||||
|
||||
bytenr = btrfs_super_block_group_root(sb);
|
||||
gen = btrfs_super_block_group_root_generation(sb);
|
||||
level = btrfs_super_block_group_root_level(sb);
|
||||
ret = load_super_root(fs_info->block_group_root, bytenr, gen, level);
|
||||
if (ret)
|
||||
btrfs_warn(fs_info, "couldn't read block group root");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
int backup_index = find_newest_super_backup(fs_info);
|
||||
@@ -2939,10 +3050,17 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < BTRFS_NUM_BACKUP_ROOTS; i++) {
|
||||
u64 generation;
|
||||
int level;
|
||||
if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) {
|
||||
struct btrfs_root *root;
|
||||
|
||||
root = btrfs_alloc_root(fs_info, BTRFS_BLOCK_GROUP_TREE_OBJECTID,
|
||||
GFP_KERNEL);
|
||||
if (!root)
|
||||
return -ENOMEM;
|
||||
fs_info->block_group_root = root;
|
||||
}
|
||||
|
||||
for (i = 0; i < BTRFS_NUM_BACKUP_ROOTS; i++) {
|
||||
if (handle_error) {
|
||||
if (!IS_ERR(tree_root->node))
|
||||
free_extent_buffer(tree_root->node);
|
||||
@@ -2967,29 +3085,13 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
generation = btrfs_super_generation(sb);
|
||||
level = btrfs_super_root_level(sb);
|
||||
tree_root->node = read_tree_block(fs_info, btrfs_super_root(sb),
|
||||
BTRFS_ROOT_TREE_OBJECTID,
|
||||
generation, level, NULL);
|
||||
if (IS_ERR(tree_root->node)) {
|
||||
handle_error = true;
|
||||
ret = PTR_ERR(tree_root->node);
|
||||
tree_root->node = NULL;
|
||||
btrfs_warn(fs_info, "couldn't read tree root");
|
||||
continue;
|
||||
|
||||
} else if (!extent_buffer_uptodate(tree_root->node)) {
|
||||
ret = load_important_roots(fs_info);
|
||||
if (ret) {
|
||||
handle_error = true;
|
||||
ret = -EIO;
|
||||
btrfs_warn(fs_info, "error while reading tree root");
|
||||
continue;
|
||||
}
|
||||
|
||||
btrfs_set_root_node(&tree_root->root_item, tree_root->node);
|
||||
tree_root->commit_root = btrfs_root_node(tree_root);
|
||||
btrfs_set_root_refs(&tree_root->root_item, 1);
|
||||
|
||||
/*
|
||||
* No need to hold btrfs_root::objectid_mutex since the fs
|
||||
* hasn't been fully initialised and we are the only user
|
||||
@@ -3009,8 +3111,8 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info)
|
||||
}
|
||||
|
||||
/* All successful */
|
||||
fs_info->generation = generation;
|
||||
fs_info->last_trans_committed = generation;
|
||||
fs_info->generation = btrfs_header_generation(tree_root->node);
|
||||
fs_info->last_trans_committed = fs_info->generation;
|
||||
fs_info->last_reloc_trans = 0;
|
||||
|
||||
/* Always begin writing backup roots after the one being used */
|
||||
@@ -3293,7 +3395,7 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
|
||||
up_read(&fs_info->cleanup_work_sem);
|
||||
|
||||
mutex_lock(&fs_info->cleaner_mutex);
|
||||
ret = btrfs_recover_relocation(fs_info->tree_root);
|
||||
ret = btrfs_recover_relocation(fs_info);
|
||||
mutex_unlock(&fs_info->cleaner_mutex);
|
||||
if (ret < 0) {
|
||||
btrfs_warn(fs_info, "failed to recover relocation: %d", ret);
|
||||
@@ -3594,21 +3696,12 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
|
||||
|
||||
generation = btrfs_super_chunk_root_generation(disk_super);
|
||||
level = btrfs_super_chunk_root_level(disk_super);
|
||||
|
||||
chunk_root->node = read_tree_block(fs_info,
|
||||
btrfs_super_chunk_root(disk_super),
|
||||
BTRFS_CHUNK_TREE_OBJECTID,
|
||||
generation, level, NULL);
|
||||
if (IS_ERR(chunk_root->node) ||
|
||||
!extent_buffer_uptodate(chunk_root->node)) {
|
||||
ret = load_super_root(chunk_root, btrfs_super_chunk_root(disk_super),
|
||||
generation, level);
|
||||
if (ret) {
|
||||
btrfs_err(fs_info, "failed to read chunk root");
|
||||
if (!IS_ERR(chunk_root->node))
|
||||
free_extent_buffer(chunk_root->node);
|
||||
chunk_root->node = NULL;
|
||||
goto fail_tree_roots;
|
||||
}
|
||||
btrfs_set_root_node(&chunk_root->root_item, chunk_root->node);
|
||||
chunk_root->commit_root = btrfs_root_node(chunk_root);
|
||||
|
||||
read_extent_buffer(chunk_root->node, fs_info->chunk_tree_uuid,
|
||||
offsetof(struct btrfs_header, chunk_tree_uuid),
|
||||
@@ -3728,7 +3821,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
|
||||
goto fail_sysfs;
|
||||
}
|
||||
|
||||
fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root,
|
||||
fs_info->cleaner_kthread = kthread_run(cleaner_kthread, fs_info,
|
||||
"btrfs-cleaner");
|
||||
if (IS_ERR(fs_info->cleaner_kthread))
|
||||
goto fail_sysfs;
|
||||
|
||||
@@ -111,6 +111,8 @@ static inline struct btrfs_root *btrfs_grab_root(struct btrfs_root *root)
|
||||
|
||||
static inline struct btrfs_root *btrfs_block_group_root(struct btrfs_fs_info *fs_info)
|
||||
{
|
||||
if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2))
|
||||
return fs_info->block_group_root;
|
||||
return btrfs_extent_root(fs_info, 0);
|
||||
}
|
||||
|
||||
|
||||
+68
-80
@@ -598,7 +598,7 @@ fail:
|
||||
static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct btrfs_path *path,
|
||||
int refs_to_drop, int *last_ref)
|
||||
int refs_to_drop)
|
||||
{
|
||||
struct btrfs_key key;
|
||||
struct btrfs_extent_data_ref *ref1 = NULL;
|
||||
@@ -631,7 +631,6 @@ static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
|
||||
|
||||
if (num_refs == 0) {
|
||||
ret = btrfs_del_item(trans, root, path);
|
||||
*last_ref = 1;
|
||||
} else {
|
||||
if (key.type == BTRFS_EXTENT_DATA_REF_KEY)
|
||||
btrfs_set_extent_data_ref_count(leaf, ref1, num_refs);
|
||||
@@ -1072,8 +1071,7 @@ static noinline_for_stack
|
||||
void update_inline_extent_backref(struct btrfs_path *path,
|
||||
struct btrfs_extent_inline_ref *iref,
|
||||
int refs_to_mod,
|
||||
struct btrfs_delayed_extent_op *extent_op,
|
||||
int *last_ref)
|
||||
struct btrfs_delayed_extent_op *extent_op)
|
||||
{
|
||||
struct extent_buffer *leaf = path->nodes[0];
|
||||
struct btrfs_extent_item *ei;
|
||||
@@ -1121,7 +1119,6 @@ void update_inline_extent_backref(struct btrfs_path *path,
|
||||
else
|
||||
btrfs_set_shared_data_ref_count(leaf, sref, refs);
|
||||
} else {
|
||||
*last_ref = 1;
|
||||
size = btrfs_extent_inline_ref_size(type);
|
||||
item_size = btrfs_item_size(leaf, path->slots[0]);
|
||||
ptr = (unsigned long)iref;
|
||||
@@ -1166,8 +1163,7 @@ int insert_inline_extent_backref(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
return -EUCLEAN;
|
||||
}
|
||||
update_inline_extent_backref(path, iref, refs_to_add,
|
||||
extent_op, NULL);
|
||||
update_inline_extent_backref(path, iref, refs_to_add, extent_op);
|
||||
} else if (ret == -ENOENT) {
|
||||
setup_inline_extent_backref(trans->fs_info, path, iref, parent,
|
||||
root_objectid, owner, offset,
|
||||
@@ -1181,21 +1177,17 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct btrfs_path *path,
|
||||
struct btrfs_extent_inline_ref *iref,
|
||||
int refs_to_drop, int is_data, int *last_ref)
|
||||
int refs_to_drop, int is_data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(!is_data && refs_to_drop != 1);
|
||||
if (iref) {
|
||||
update_inline_extent_backref(path, iref, -refs_to_drop, NULL,
|
||||
last_ref);
|
||||
} else if (is_data) {
|
||||
ret = remove_extent_data_ref(trans, root, path, refs_to_drop,
|
||||
last_ref);
|
||||
} else {
|
||||
*last_ref = 1;
|
||||
if (iref)
|
||||
update_inline_extent_backref(path, iref, -refs_to_drop, NULL);
|
||||
else if (is_data)
|
||||
ret = remove_extent_data_ref(trans, root, path, refs_to_drop);
|
||||
else
|
||||
ret = btrfs_del_item(trans, root, path);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2766,12 +2758,11 @@ static int unpin_extent_range(struct btrfs_fs_info *fs_info,
|
||||
spin_unlock(&cache->lock);
|
||||
if (!readonly && return_free_space &&
|
||||
global_rsv->space_info == space_info) {
|
||||
u64 to_add = len;
|
||||
|
||||
spin_lock(&global_rsv->lock);
|
||||
if (!global_rsv->full) {
|
||||
to_add = min(len, global_rsv->size -
|
||||
global_rsv->reserved);
|
||||
u64 to_add = min(len, global_rsv->size -
|
||||
global_rsv->reserved);
|
||||
|
||||
global_rsv->reserved += to_add;
|
||||
btrfs_space_info_update_bytes_may_use(fs_info,
|
||||
space_info, to_add);
|
||||
@@ -2862,6 +2853,35 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_free_extent_accounting(struct btrfs_trans_handle *trans,
|
||||
u64 bytenr, u64 num_bytes, bool is_data)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (is_data) {
|
||||
struct btrfs_root *csum_root;
|
||||
|
||||
csum_root = btrfs_csum_root(trans->fs_info, bytenr);
|
||||
ret = btrfs_del_csums(trans, csum_root, bytenr, num_bytes);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = add_to_free_space_tree(trans, bytenr, num_bytes);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = btrfs_update_block_group(trans, bytenr, num_bytes, false);
|
||||
if (ret)
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop one or more refs of @node.
|
||||
*
|
||||
@@ -2943,7 +2963,6 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||
u64 refs;
|
||||
u64 bytenr = node->bytenr;
|
||||
u64 num_bytes = node->num_bytes;
|
||||
int last_ref = 0;
|
||||
bool skinny_metadata = btrfs_fs_incompat(info, SKINNY_METADATA);
|
||||
|
||||
extent_root = btrfs_extent_root(info, bytenr);
|
||||
@@ -3010,8 +3029,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
/* Must be SHARED_* item, remove the backref first */
|
||||
ret = remove_extent_backref(trans, extent_root, path,
|
||||
NULL, refs_to_drop, is_data,
|
||||
&last_ref);
|
||||
NULL, refs_to_drop, is_data);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto out;
|
||||
@@ -3136,8 +3154,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
if (found_extent) {
|
||||
ret = remove_extent_backref(trans, extent_root, path,
|
||||
iref, refs_to_drop, is_data,
|
||||
&last_ref);
|
||||
iref, refs_to_drop, is_data);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto out;
|
||||
@@ -3182,7 +3199,6 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
}
|
||||
|
||||
last_ref = 1;
|
||||
ret = btrfs_del_items(trans, extent_root, path, path->slots[0],
|
||||
num_to_del);
|
||||
if (ret) {
|
||||
@@ -3191,28 +3207,7 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
|
||||
}
|
||||
btrfs_release_path(path);
|
||||
|
||||
if (is_data) {
|
||||
struct btrfs_root *csum_root;
|
||||
csum_root = btrfs_csum_root(info, bytenr);
|
||||
ret = btrfs_del_csums(trans, csum_root, bytenr,
|
||||
num_bytes);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = add_to_free_space_tree(trans, bytenr, num_bytes);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = btrfs_update_block_group(trans, bytenr, num_bytes, false);
|
||||
if (ret) {
|
||||
btrfs_abort_transaction(trans, ret);
|
||||
goto out;
|
||||
}
|
||||
ret = do_free_extent_accounting(trans, bytenr, num_bytes, is_data);
|
||||
}
|
||||
btrfs_release_path(path);
|
||||
|
||||
@@ -4605,6 +4600,28 @@ int btrfs_pin_reserved_extent(struct btrfs_trans_handle *trans, u64 start,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int alloc_reserved_extent(struct btrfs_trans_handle *trans, u64 bytenr,
|
||||
u64 num_bytes)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = trans->fs_info;
|
||||
int ret;
|
||||
|
||||
ret = remove_from_free_space_tree(trans, bytenr, num_bytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = btrfs_update_block_group(trans, bytenr, num_bytes, true);
|
||||
if (ret) {
|
||||
ASSERT(!ret);
|
||||
btrfs_err(fs_info, "update block group failed for %llu %llu",
|
||||
bytenr, num_bytes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
trace_btrfs_reserved_extent_alloc(fs_info, bytenr, num_bytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
|
||||
u64 parent, u64 root_objectid,
|
||||
u64 flags, u64 owner, u64 offset,
|
||||
@@ -4665,18 +4682,7 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
btrfs_free_path(path);
|
||||
|
||||
ret = remove_from_free_space_tree(trans, ins->objectid, ins->offset);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = btrfs_update_block_group(trans, ins->objectid, ins->offset, true);
|
||||
if (ret) { /* -ENOENT, logic error */
|
||||
btrfs_err(fs_info, "update block group failed for %llu %llu",
|
||||
ins->objectid, ins->offset);
|
||||
BUG();
|
||||
}
|
||||
trace_btrfs_reserved_extent_alloc(fs_info, ins->objectid, ins->offset);
|
||||
return ret;
|
||||
return alloc_reserved_extent(trans, ins->objectid, ins->offset);
|
||||
}
|
||||
|
||||
static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
|
||||
@@ -4694,7 +4700,6 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
|
||||
struct extent_buffer *leaf;
|
||||
struct btrfs_delayed_tree_ref *ref;
|
||||
u32 size = sizeof(*extent_item) + sizeof(*iref);
|
||||
u64 num_bytes;
|
||||
u64 flags = extent_op->flags_to_set;
|
||||
bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA);
|
||||
|
||||
@@ -4704,12 +4709,10 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
|
||||
if (skinny_metadata) {
|
||||
extent_key.offset = ref->level;
|
||||
extent_key.type = BTRFS_METADATA_ITEM_KEY;
|
||||
num_bytes = fs_info->nodesize;
|
||||
} else {
|
||||
extent_key.offset = node->num_bytes;
|
||||
extent_key.type = BTRFS_EXTENT_ITEM_KEY;
|
||||
size += sizeof(*block_info);
|
||||
num_bytes = node->num_bytes;
|
||||
}
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
@@ -4754,22 +4757,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
btrfs_free_path(path);
|
||||
|
||||
ret = remove_from_free_space_tree(trans, extent_key.objectid,
|
||||
num_bytes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = btrfs_update_block_group(trans, extent_key.objectid,
|
||||
fs_info->nodesize, true);
|
||||
if (ret) { /* -ENOENT, logic error */
|
||||
btrfs_err(fs_info, "update block group failed for %llu %llu",
|
||||
extent_key.objectid, extent_key.offset);
|
||||
BUG();
|
||||
}
|
||||
|
||||
trace_btrfs_reserved_extent_alloc(fs_info, extent_key.objectid,
|
||||
fs_info->nodesize);
|
||||
return ret;
|
||||
return alloc_reserved_extent(trans, node->bytenr, fs_info->nodesize);
|
||||
}
|
||||
|
||||
int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
|
||||
|
||||
+26
-19
@@ -2610,6 +2610,7 @@ static bool btrfs_check_repairable(struct inode *inode,
|
||||
* a good copy of the failed sector and if we succeed, we have setup
|
||||
* everything for repair_io_failure to do the rest for us.
|
||||
*/
|
||||
ASSERT(failed_mirror);
|
||||
failrec->failed_mirror = failed_mirror;
|
||||
failrec->this_mirror++;
|
||||
if (failrec->this_mirror == failed_mirror)
|
||||
@@ -2639,7 +2640,6 @@ int btrfs_repair_one_sector(struct inode *inode,
|
||||
const int icsum = bio_offset >> fs_info->sectorsize_bits;
|
||||
struct bio *repair_bio;
|
||||
struct btrfs_bio *repair_bbio;
|
||||
blk_status_t status;
|
||||
|
||||
btrfs_debug(fs_info,
|
||||
"repair read error: read error at %llu", start);
|
||||
@@ -2678,13 +2678,13 @@ int btrfs_repair_one_sector(struct inode *inode,
|
||||
"repair read error: submitting new read to mirror %d",
|
||||
failrec->this_mirror);
|
||||
|
||||
status = submit_bio_hook(inode, repair_bio, failrec->this_mirror,
|
||||
failrec->bio_flags);
|
||||
if (status) {
|
||||
free_io_failure(failure_tree, tree, failrec);
|
||||
bio_put(repair_bio);
|
||||
}
|
||||
return blk_status_to_errno(status);
|
||||
/*
|
||||
* At this point we have a bio, so any errors from submit_bio_hook()
|
||||
* will be handled by the endio on the repair_bio, so we can't return an
|
||||
* error here.
|
||||
*/
|
||||
submit_bio_hook(inode, repair_bio, failrec->this_mirror, failrec->bio_flags);
|
||||
return BLK_STS_OK;
|
||||
}
|
||||
|
||||
static void end_page_read(struct page *page, bool uptodate, u64 start, u32 len)
|
||||
@@ -3067,6 +3067,14 @@ static void end_bio_extent_readpage(struct bio *bio)
|
||||
goto readpage_ok;
|
||||
|
||||
if (is_data_inode(inode)) {
|
||||
/*
|
||||
* If we failed to submit the IO at all we'll have a
|
||||
* mirror_num == 0, in which case we need to just mark
|
||||
* the page with an error and unlock it and carry on.
|
||||
*/
|
||||
if (mirror == 0)
|
||||
goto readpage_ok;
|
||||
|
||||
/*
|
||||
* btrfs_submit_read_repair() will handle all the good
|
||||
* and bad sectors, we just continue to the next bvec.
|
||||
@@ -3534,7 +3542,7 @@ __get_extent_map(struct inode *inode, struct page *page, size_t pg_offset,
|
||||
}
|
||||
|
||||
em = btrfs_get_extent(BTRFS_I(inode), page, pg_offset, start, len);
|
||||
if (em_cached && !IS_ERR_OR_NULL(em)) {
|
||||
if (em_cached && !IS_ERR(em)) {
|
||||
BUG_ON(*em_cached);
|
||||
refcount_inc(&em->refs);
|
||||
*em_cached = em;
|
||||
@@ -3563,7 +3571,6 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
|
||||
u64 cur_end;
|
||||
struct extent_map *em;
|
||||
int ret = 0;
|
||||
int nr = 0;
|
||||
size_t pg_offset = 0;
|
||||
size_t iosize;
|
||||
size_t blocksize = inode->i_sb->s_blocksize;
|
||||
@@ -3608,9 +3615,10 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
|
||||
}
|
||||
em = __get_extent_map(inode, page, pg_offset, cur,
|
||||
end - cur + 1, em_cached);
|
||||
if (IS_ERR_OR_NULL(em)) {
|
||||
if (IS_ERR(em)) {
|
||||
unlock_extent(tree, cur, end);
|
||||
end_page_read(page, false, cur, end + 1 - cur);
|
||||
ret = PTR_ERR(em);
|
||||
break;
|
||||
}
|
||||
extent_offset = cur - em->start;
|
||||
@@ -3721,9 +3729,7 @@ int btrfs_do_readpage(struct page *page, struct extent_map **em_cached,
|
||||
end_bio_extent_readpage, 0,
|
||||
this_bio_flag,
|
||||
force_bio_submit);
|
||||
if (!ret) {
|
||||
nr++;
|
||||
} else {
|
||||
if (ret) {
|
||||
unlock_extent(tree, cur, cur + iosize - 1);
|
||||
end_page_read(page, false, cur, iosize);
|
||||
goto out;
|
||||
@@ -3951,7 +3957,7 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode,
|
||||
}
|
||||
|
||||
em = btrfs_get_extent(inode, NULL, 0, cur, end - cur + 1);
|
||||
if (IS_ERR_OR_NULL(em)) {
|
||||
if (IS_ERR(em)) {
|
||||
btrfs_page_set_error(fs_info, page, cur, end - cur + 1);
|
||||
ret = PTR_ERR_OR_ZERO(em);
|
||||
break;
|
||||
@@ -4780,11 +4786,12 @@ static int submit_eb_page(struct page *page, struct writeback_control *wbc,
|
||||
return ret;
|
||||
}
|
||||
if (cache) {
|
||||
/* Impiles write in zoned mode */
|
||||
btrfs_put_block_group(cache);
|
||||
/* Mark the last eb in a block group */
|
||||
/*
|
||||
* Implies write in zoned mode. Mark the last eb in a block group.
|
||||
*/
|
||||
if (cache->seq_zone && eb->start + eb->len == cache->zone_capacity)
|
||||
set_bit(EXTENT_BUFFER_ZONE_FINISH, &eb->bflags);
|
||||
btrfs_put_block_group(cache);
|
||||
}
|
||||
ret = write_one_eb(eb, wbc, epd);
|
||||
free_extent_buffer(eb);
|
||||
@@ -5390,7 +5397,7 @@ static struct extent_map *get_extent_skip_holes(struct btrfs_inode *inode,
|
||||
break;
|
||||
len = ALIGN(len, sectorsize);
|
||||
em = btrfs_get_extent_fiemap(inode, offset, len);
|
||||
if (IS_ERR_OR_NULL(em))
|
||||
if (IS_ERR(em))
|
||||
return em;
|
||||
|
||||
/* if this isn't a hole return it */
|
||||
|
||||
@@ -492,6 +492,8 @@ struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
|
||||
*/
|
||||
void remove_extent_mapping(struct extent_map_tree *tree, struct extent_map *em)
|
||||
{
|
||||
lockdep_assert_held_write(&tree->lock);
|
||||
|
||||
WARN_ON(test_bit(EXTENT_FLAG_PINNED, &em->flags));
|
||||
rb_erase_cached(&em->rb_node, &tree->map);
|
||||
if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags))
|
||||
@@ -506,6 +508,8 @@ void replace_extent_mapping(struct extent_map_tree *tree,
|
||||
struct extent_map *new,
|
||||
int modified)
|
||||
{
|
||||
lockdep_assert_held_write(&tree->lock);
|
||||
|
||||
WARN_ON(test_bit(EXTENT_FLAG_PINNED, &cur->flags));
|
||||
ASSERT(extent_map_in_tree(cur));
|
||||
if (!test_bit(EXTENT_FLAG_LOGGING, &cur->flags))
|
||||
|
||||
+41
-35
@@ -305,7 +305,7 @@ found:
|
||||
read_extent_buffer(path->nodes[0], dst, (unsigned long)item,
|
||||
ret * csum_size);
|
||||
out:
|
||||
if (ret == -ENOENT)
|
||||
if (ret == -ENOENT || ret == -EFBIG)
|
||||
ret = 0;
|
||||
return ret;
|
||||
}
|
||||
@@ -368,6 +368,7 @@ blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u8 *dst
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
||||
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
|
||||
struct btrfs_bio *bbio = NULL;
|
||||
struct btrfs_path *path;
|
||||
const u32 sectorsize = fs_info->sectorsize;
|
||||
const u32 csum_size = fs_info->csum_size;
|
||||
@@ -377,6 +378,7 @@ blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u8 *dst
|
||||
u8 *csum;
|
||||
const unsigned int nblocks = orig_len >> fs_info->sectorsize_bits;
|
||||
int count = 0;
|
||||
blk_status_t ret = BLK_STS_OK;
|
||||
|
||||
if ((BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) ||
|
||||
test_bit(BTRFS_FS_STATE_NO_CSUMS, &fs_info->fs_state))
|
||||
@@ -400,7 +402,7 @@ blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u8 *dst
|
||||
return BLK_STS_RESOURCE;
|
||||
|
||||
if (!dst) {
|
||||
struct btrfs_bio *bbio = btrfs_bio(bio);
|
||||
bbio = btrfs_bio(bio);
|
||||
|
||||
if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
|
||||
bbio->csum = kmalloc_array(nblocks, csum_size, GFP_NOFS);
|
||||
@@ -456,21 +458,27 @@ blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u8 *dst
|
||||
|
||||
count = search_csum_tree(fs_info, path, cur_disk_bytenr,
|
||||
search_len, csum_dst);
|
||||
if (count <= 0) {
|
||||
/*
|
||||
* Either we hit a critical error or we didn't find
|
||||
* the csum.
|
||||
* Either way, we put zero into the csums dst, and skip
|
||||
* to the next sector.
|
||||
*/
|
||||
if (count < 0) {
|
||||
ret = errno_to_blk_status(count);
|
||||
if (bbio)
|
||||
btrfs_bio_free_csum(bbio);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We didn't find a csum for this range. We need to make sure
|
||||
* we complain loudly about this, because we are not NODATASUM.
|
||||
*
|
||||
* However for the DATA_RELOC inode we could potentially be
|
||||
* relocating data extents for a NODATASUM inode, so the inode
|
||||
* itself won't be marked with NODATASUM, but the extent we're
|
||||
* copying is in fact NODATASUM. If we don't find a csum we
|
||||
* assume this is the case.
|
||||
*/
|
||||
if (count == 0) {
|
||||
memset(csum_dst, 0, csum_size);
|
||||
count = 1;
|
||||
|
||||
/*
|
||||
* For data reloc inode, we need to mark the range
|
||||
* NODATASUM so that balance won't report false csum
|
||||
* error.
|
||||
*/
|
||||
if (BTRFS_I(inode)->root->root_key.objectid ==
|
||||
BTRFS_DATA_RELOC_TREE_OBJECTID) {
|
||||
u64 file_offset;
|
||||
@@ -491,7 +499,7 @@ blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u8 *dst
|
||||
}
|
||||
|
||||
btrfs_free_path(path);
|
||||
return BLK_STS_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
|
||||
@@ -612,32 +620,33 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* btrfs_csum_one_bio - Calculates checksums of the data contained inside a bio
|
||||
/**
|
||||
* Calculate checksums of the data contained inside a bio
|
||||
*
|
||||
* @inode: Owner of the data inside the bio
|
||||
* @bio: Contains the data to be checksummed
|
||||
* @file_start: offset in file this bio begins to describe
|
||||
* @contig: Boolean. If true/1 means all bio vecs in this bio are
|
||||
* contiguous and they begin at @file_start in the file. False/0
|
||||
* means this bio can contain potentially discontiguous bio vecs
|
||||
* so the logical offset of each should be calculated separately.
|
||||
* @offset: If (u64)-1, @bio may contain discontiguous bio vecs, so the
|
||||
* file offsets are determined from the page offsets in the bio.
|
||||
* Otherwise, this is the starting file offset of the bio vecs in
|
||||
* @bio, which must be contiguous.
|
||||
* @one_ordered: If true, @bio only refers to one ordered extent.
|
||||
*/
|
||||
blk_status_t btrfs_csum_one_bio(struct btrfs_inode *inode, struct bio *bio,
|
||||
u64 file_start, int contig)
|
||||
u64 offset, bool one_ordered)
|
||||
{
|
||||
struct btrfs_fs_info *fs_info = inode->root->fs_info;
|
||||
SHASH_DESC_ON_STACK(shash, fs_info->csum_shash);
|
||||
struct btrfs_ordered_sum *sums;
|
||||
struct btrfs_ordered_extent *ordered = NULL;
|
||||
const bool use_page_offsets = (offset == (u64)-1);
|
||||
char *data;
|
||||
struct bvec_iter iter;
|
||||
struct bio_vec bvec;
|
||||
int index;
|
||||
int nr_sectors;
|
||||
unsigned int blockcount;
|
||||
unsigned long total_bytes = 0;
|
||||
unsigned long this_sum_bytes = 0;
|
||||
int i;
|
||||
u64 offset;
|
||||
unsigned nofs_flag;
|
||||
|
||||
nofs_flag = memalloc_nofs_save();
|
||||
@@ -651,18 +660,13 @@ blk_status_t btrfs_csum_one_bio(struct btrfs_inode *inode, struct bio *bio,
|
||||
sums->len = bio->bi_iter.bi_size;
|
||||
INIT_LIST_HEAD(&sums->list);
|
||||
|
||||
if (contig)
|
||||
offset = file_start;
|
||||
else
|
||||
offset = 0; /* shut up gcc */
|
||||
|
||||
sums->bytenr = bio->bi_iter.bi_sector << 9;
|
||||
index = 0;
|
||||
|
||||
shash->tfm = fs_info->csum_shash;
|
||||
|
||||
bio_for_each_segment(bvec, bio, iter) {
|
||||
if (!contig)
|
||||
if (use_page_offsets)
|
||||
offset = page_offset(bvec.bv_page) + bvec.bv_offset;
|
||||
|
||||
if (!ordered) {
|
||||
@@ -681,13 +685,14 @@ blk_status_t btrfs_csum_one_bio(struct btrfs_inode *inode, struct bio *bio,
|
||||
}
|
||||
}
|
||||
|
||||
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info,
|
||||
blockcount = BTRFS_BYTES_TO_BLKS(fs_info,
|
||||
bvec.bv_len + fs_info->sectorsize
|
||||
- 1);
|
||||
|
||||
for (i = 0; i < nr_sectors; i++) {
|
||||
if (offset >= ordered->file_offset + ordered->num_bytes ||
|
||||
offset < ordered->file_offset) {
|
||||
for (i = 0; i < blockcount; i++) {
|
||||
if (!one_ordered &&
|
||||
!in_range(offset, ordered->file_offset,
|
||||
ordered->num_bytes)) {
|
||||
unsigned long bytes_left;
|
||||
|
||||
sums->len = this_sum_bytes;
|
||||
@@ -1211,6 +1216,7 @@ void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode,
|
||||
extent_start = key.offset;
|
||||
extent_end = btrfs_file_extent_end(path);
|
||||
em->ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
|
||||
em->generation = btrfs_file_extent_generation(leaf, fi);
|
||||
if (type == BTRFS_FILE_EXTENT_REG ||
|
||||
type == BTRFS_FILE_EXTENT_PREALLOC) {
|
||||
em->start = extent_start;
|
||||
|
||||
+59
-20
@@ -691,7 +691,6 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
|
||||
int modify_tree = -1;
|
||||
int update_refs;
|
||||
int found = 0;
|
||||
int leafs_visited = 0;
|
||||
struct btrfs_path *path = args->path;
|
||||
|
||||
args->bytes_found = 0;
|
||||
@@ -729,7 +728,6 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
|
||||
path->slots[0]--;
|
||||
}
|
||||
ret = 0;
|
||||
leafs_visited++;
|
||||
next_slot:
|
||||
leaf = path->nodes[0];
|
||||
if (path->slots[0] >= btrfs_header_nritems(leaf)) {
|
||||
@@ -741,7 +739,6 @@ next_slot:
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
leafs_visited++;
|
||||
leaf = path->nodes[0];
|
||||
recow = 1;
|
||||
}
|
||||
@@ -987,7 +984,7 @@ delete_extent_item:
|
||||
* which case it unlocked our path, so check path->locks[0] matches a
|
||||
* write lock.
|
||||
*/
|
||||
if (!ret && args->replace_extent && leafs_visited == 1 &&
|
||||
if (!ret && args->replace_extent &&
|
||||
path->locks[0] == BTRFS_WRITE_LOCK &&
|
||||
btrfs_leaf_free_space(leaf) >=
|
||||
sizeof(struct btrfs_item) + args->extent_item_size) {
|
||||
@@ -1722,7 +1719,8 @@ static noinline ssize_t btrfs_buffered_write(struct kiocb *iocb,
|
||||
fs_info->sectorsize);
|
||||
WARN_ON(reserve_bytes == 0);
|
||||
ret = btrfs_delalloc_reserve_metadata(BTRFS_I(inode),
|
||||
reserve_bytes);
|
||||
reserve_bytes,
|
||||
reserve_bytes);
|
||||
if (ret) {
|
||||
if (!only_release_metadata)
|
||||
btrfs_free_reserved_data_space(BTRFS_I(inode),
|
||||
@@ -2039,12 +2037,43 @@ out:
|
||||
return err < 0 ? err : written;
|
||||
}
|
||||
|
||||
static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
|
||||
struct iov_iter *from)
|
||||
static ssize_t btrfs_encoded_write(struct kiocb *iocb, struct iov_iter *from,
|
||||
const struct btrfs_ioctl_encoded_io_args *encoded)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct inode *inode = file_inode(file);
|
||||
loff_t count;
|
||||
ssize_t ret;
|
||||
|
||||
btrfs_inode_lock(inode, 0);
|
||||
count = encoded->len;
|
||||
ret = generic_write_checks_count(iocb, &count);
|
||||
if (ret == 0 && count != encoded->len) {
|
||||
/*
|
||||
* The write got truncated by generic_write_checks_count(). We
|
||||
* can't do a partial encoded write.
|
||||
*/
|
||||
ret = -EFBIG;
|
||||
}
|
||||
if (ret || encoded->len == 0)
|
||||
goto out;
|
||||
|
||||
ret = btrfs_write_check(iocb, from, encoded->len);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = btrfs_do_encoded_write(iocb, from, encoded);
|
||||
out:
|
||||
btrfs_inode_unlock(inode, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t btrfs_do_write_iter(struct kiocb *iocb, struct iov_iter *from,
|
||||
const struct btrfs_ioctl_encoded_io_args *encoded)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct btrfs_inode *inode = BTRFS_I(file_inode(file));
|
||||
ssize_t num_written = 0;
|
||||
ssize_t num_written, num_sync;
|
||||
const bool sync = iocb->ki_flags & IOCB_DSYNC;
|
||||
|
||||
/*
|
||||
@@ -2055,22 +2084,28 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
|
||||
if (BTRFS_FS_ERROR(inode->root->fs_info))
|
||||
return -EROFS;
|
||||
|
||||
if (!(iocb->ki_flags & IOCB_DIRECT) &&
|
||||
(iocb->ki_flags & IOCB_NOWAIT))
|
||||
if ((iocb->ki_flags & IOCB_NOWAIT) && !(iocb->ki_flags & IOCB_DIRECT))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (sync)
|
||||
atomic_inc(&inode->sync_writers);
|
||||
|
||||
if (iocb->ki_flags & IOCB_DIRECT)
|
||||
num_written = btrfs_direct_write(iocb, from);
|
||||
else
|
||||
num_written = btrfs_buffered_write(iocb, from);
|
||||
if (encoded) {
|
||||
num_written = btrfs_encoded_write(iocb, from, encoded);
|
||||
num_sync = encoded->len;
|
||||
} else if (iocb->ki_flags & IOCB_DIRECT) {
|
||||
num_written = num_sync = btrfs_direct_write(iocb, from);
|
||||
} else {
|
||||
num_written = num_sync = btrfs_buffered_write(iocb, from);
|
||||
}
|
||||
|
||||
btrfs_set_inode_last_sub_trans(inode);
|
||||
|
||||
if (num_written > 0)
|
||||
num_written = generic_write_sync(iocb, num_written);
|
||||
if (num_sync > 0) {
|
||||
num_sync = generic_write_sync(iocb, num_sync);
|
||||
if (num_sync < 0)
|
||||
num_written = num_sync;
|
||||
}
|
||||
|
||||
if (sync)
|
||||
atomic_dec(&inode->sync_writers);
|
||||
@@ -2079,6 +2114,11 @@ static ssize_t btrfs_file_write_iter(struct kiocb *iocb,
|
||||
return num_written;
|
||||
}
|
||||
|
||||
static ssize_t btrfs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
{
|
||||
return btrfs_do_write_iter(iocb, from, NULL);
|
||||
}
|
||||
|
||||
int btrfs_release_file(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct btrfs_file_private *private = filp->private_data;
|
||||
@@ -2474,7 +2514,7 @@ out:
|
||||
hole_em = alloc_extent_map();
|
||||
if (!hole_em) {
|
||||
btrfs_drop_extent_cache(inode, offset, end - 1, 0);
|
||||
set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags);
|
||||
btrfs_set_inode_full_sync(inode);
|
||||
} else {
|
||||
hole_em->start = offset;
|
||||
hole_em->len = end - offset;
|
||||
@@ -2495,8 +2535,7 @@ out:
|
||||
} while (ret == -EEXIST);
|
||||
free_extent_map(hole_em);
|
||||
if (ret)
|
||||
set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
|
||||
&inode->runtime_flags);
|
||||
btrfs_set_inode_full_sync(inode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2850,7 +2889,7 @@ int btrfs_replace_file_extents(struct btrfs_inode *inode,
|
||||
* maps for the replacement extents (or holes).
|
||||
*/
|
||||
if (extent_info && !extent_info->is_new_extent)
|
||||
set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &inode->runtime_flags);
|
||||
btrfs_set_inode_full_sync(inode);
|
||||
|
||||
if (ret)
|
||||
goto out_trans;
|
||||
|
||||
@@ -25,6 +25,8 @@ static struct btrfs_root *btrfs_free_space_root(
|
||||
.offset = 0,
|
||||
};
|
||||
|
||||
if (btrfs_fs_incompat(block_group->fs_info, EXTENT_TREE_V2))
|
||||
key.offset = block_group->global_root_id;
|
||||
return btrfs_global_root(block_group->fs_info, &key);
|
||||
}
|
||||
|
||||
|
||||
+938
-245
File diff suppressed because it is too large
Load Diff
+266
-43
@@ -28,6 +28,7 @@
|
||||
#include <linux/iversion.h>
|
||||
#include <linux/fileattr.h>
|
||||
#include <linux/fsverity.h>
|
||||
#include <linux/sched/xacct.h>
|
||||
#include "ctree.h"
|
||||
#include "disk-io.h"
|
||||
#include "export.h"
|
||||
@@ -88,6 +89,24 @@ struct btrfs_ioctl_send_args_32 {
|
||||
|
||||
#define BTRFS_IOC_SEND_32 _IOW(BTRFS_IOCTL_MAGIC, 38, \
|
||||
struct btrfs_ioctl_send_args_32)
|
||||
|
||||
struct btrfs_ioctl_encoded_io_args_32 {
|
||||
compat_uptr_t iov;
|
||||
compat_ulong_t iovcnt;
|
||||
__s64 offset;
|
||||
__u64 flags;
|
||||
__u64 len;
|
||||
__u64 unencoded_len;
|
||||
__u64 unencoded_offset;
|
||||
__u32 compression;
|
||||
__u32 encryption;
|
||||
__u8 reserved[64];
|
||||
};
|
||||
|
||||
#define BTRFS_IOC_ENCODED_READ_32 _IOR(BTRFS_IOCTL_MAGIC, 64, \
|
||||
struct btrfs_ioctl_encoded_io_args_32)
|
||||
#define BTRFS_IOC_ENCODED_WRITE_32 _IOW(BTRFS_IOCTL_MAGIC, 64, \
|
||||
struct btrfs_ioctl_encoded_io_args_32)
|
||||
#endif
|
||||
|
||||
/* Mask out flags that are inappropriate for the given type of inode. */
|
||||
@@ -440,10 +459,8 @@ void btrfs_exclop_balance(struct btrfs_fs_info *fs_info,
|
||||
}
|
||||
}
|
||||
|
||||
static int btrfs_ioctl_getversion(struct file *file, int __user *arg)
|
||||
static int btrfs_ioctl_getversion(struct inode *inode, int __user *arg)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
|
||||
return put_user(inode->i_generation, arg);
|
||||
}
|
||||
|
||||
@@ -753,6 +770,13 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
|
||||
struct btrfs_trans_handle *trans;
|
||||
int ret;
|
||||
|
||||
/* We do not support snapshotting right now. */
|
||||
if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) {
|
||||
btrfs_warn(fs_info,
|
||||
"extent tree v2 doesn't support snapshotting yet");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!test_bit(BTRFS_ROOT_SHAREABLE, &root->state))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -1522,6 +1546,7 @@ next:
|
||||
}
|
||||
|
||||
#define CLUSTER_SIZE (SZ_256K)
|
||||
static_assert(IS_ALIGNED(CLUSTER_SIZE, PAGE_SIZE));
|
||||
|
||||
/*
|
||||
* Defrag one contiguous target range.
|
||||
@@ -1667,7 +1692,6 @@ static int defrag_one_cluster(struct btrfs_inode *inode,
|
||||
LIST_HEAD(target_list);
|
||||
int ret;
|
||||
|
||||
BUILD_BUG_ON(!IS_ALIGNED(CLUSTER_SIZE, PAGE_SIZE));
|
||||
ret = defrag_collect_targets(inode, start, len, extent_thresh,
|
||||
newer_than, do_compress, false,
|
||||
&target_list, NULL);
|
||||
@@ -1810,9 +1834,6 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
|
||||
u64 last_scanned = cur;
|
||||
u64 cluster_end;
|
||||
|
||||
/* The cluster size 256K should always be page aligned */
|
||||
BUILD_BUG_ON(!IS_ALIGNED(CLUSTER_SIZE, PAGE_SIZE));
|
||||
|
||||
if (btrfs_defrag_cancelled(fs_info)) {
|
||||
ret = -EAGAIN;
|
||||
break;
|
||||
@@ -2229,10 +2250,9 @@ free_args:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static noinline int btrfs_ioctl_subvol_getflags(struct file *file,
|
||||
static noinline int btrfs_ioctl_subvol_getflags(struct inode *inode,
|
||||
void __user *arg)
|
||||
{
|
||||
struct inode *inode = file_inode(file);
|
||||
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
||||
struct btrfs_root *root = BTRFS_I(inode)->root;
|
||||
int ret = 0;
|
||||
@@ -2562,12 +2582,11 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static noinline int btrfs_ioctl_tree_search(struct file *file,
|
||||
void __user *argp)
|
||||
static noinline int btrfs_ioctl_tree_search(struct inode *inode,
|
||||
void __user *argp)
|
||||
{
|
||||
struct btrfs_ioctl_search_args __user *uargs;
|
||||
struct btrfs_ioctl_search_key sk;
|
||||
struct inode *inode;
|
||||
int ret;
|
||||
size_t buf_size;
|
||||
|
||||
@@ -2581,7 +2600,6 @@ static noinline int btrfs_ioctl_tree_search(struct file *file,
|
||||
|
||||
buf_size = sizeof(uargs->buf);
|
||||
|
||||
inode = file_inode(file);
|
||||
ret = search_ioctl(inode, &sk, &buf_size, uargs->buf);
|
||||
|
||||
/*
|
||||
@@ -2596,12 +2614,11 @@ static noinline int btrfs_ioctl_tree_search(struct file *file,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static noinline int btrfs_ioctl_tree_search_v2(struct file *file,
|
||||
static noinline int btrfs_ioctl_tree_search_v2(struct inode *inode,
|
||||
void __user *argp)
|
||||
{
|
||||
struct btrfs_ioctl_search_args_v2 __user *uarg;
|
||||
struct btrfs_ioctl_search_args_v2 args;
|
||||
struct inode *inode;
|
||||
int ret;
|
||||
size_t buf_size;
|
||||
const size_t buf_limit = SZ_16M;
|
||||
@@ -2620,7 +2637,6 @@ static noinline int btrfs_ioctl_tree_search_v2(struct file *file,
|
||||
if (buf_size > buf_limit)
|
||||
buf_size = buf_limit;
|
||||
|
||||
inode = file_inode(file);
|
||||
ret = search_ioctl(inode, &args.key, &buf_size,
|
||||
(char __user *)(&uarg->buf[0]));
|
||||
if (ret == 0 && copy_to_user(&uarg->key, &args.key, sizeof(args.key)))
|
||||
@@ -2871,25 +2887,22 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static noinline int btrfs_ioctl_ino_lookup(struct file *file,
|
||||
static noinline int btrfs_ioctl_ino_lookup(struct btrfs_root *root,
|
||||
void __user *argp)
|
||||
{
|
||||
struct btrfs_ioctl_ino_lookup_args *args;
|
||||
struct inode *inode;
|
||||
int ret = 0;
|
||||
|
||||
args = memdup_user(argp, sizeof(*args));
|
||||
if (IS_ERR(args))
|
||||
return PTR_ERR(args);
|
||||
|
||||
inode = file_inode(file);
|
||||
|
||||
/*
|
||||
* Unprivileged query to obtain the containing subvolume root id. The
|
||||
* path is reset so it's consistent with btrfs_search_path_in_tree.
|
||||
*/
|
||||
if (args->treeid == 0)
|
||||
args->treeid = BTRFS_I(inode)->root->root_key.objectid;
|
||||
args->treeid = root->root_key.objectid;
|
||||
|
||||
if (args->objectid == BTRFS_FIRST_FREE_OBJECTID) {
|
||||
args->name[0] = 0;
|
||||
@@ -2901,7 +2914,7 @@ static noinline int btrfs_ioctl_ino_lookup(struct file *file,
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = btrfs_search_path_in_tree(BTRFS_I(inode)->root->fs_info,
|
||||
ret = btrfs_search_path_in_tree(root->fs_info,
|
||||
args->treeid, args->objectid,
|
||||
args->name);
|
||||
|
||||
@@ -2957,7 +2970,7 @@ static int btrfs_ioctl_ino_lookup_user(struct file *file, void __user *argp)
|
||||
}
|
||||
|
||||
/* Get the subvolume information in BTRFS_ROOT_ITEM and BTRFS_ROOT_BACKREF */
|
||||
static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp)
|
||||
static int btrfs_ioctl_get_subvol_info(struct inode *inode, void __user *argp)
|
||||
{
|
||||
struct btrfs_ioctl_get_subvol_info_args *subvol_info;
|
||||
struct btrfs_fs_info *fs_info;
|
||||
@@ -2969,7 +2982,6 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp)
|
||||
struct extent_buffer *leaf;
|
||||
unsigned long item_off;
|
||||
unsigned long item_len;
|
||||
struct inode *inode;
|
||||
int slot;
|
||||
int ret = 0;
|
||||
|
||||
@@ -2983,7 +2995,6 @@ static int btrfs_ioctl_get_subvol_info(struct file *file, void __user *argp)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
inode = file_inode(file);
|
||||
fs_info = BTRFS_I(inode)->root->fs_info;
|
||||
|
||||
/* Get root_item of inode's subvolume */
|
||||
@@ -3077,15 +3088,14 @@ out_free:
|
||||
* Return ROOT_REF information of the subvolume containing this inode
|
||||
* except the subvolume name.
|
||||
*/
|
||||
static int btrfs_ioctl_get_subvol_rootref(struct file *file, void __user *argp)
|
||||
static int btrfs_ioctl_get_subvol_rootref(struct btrfs_root *root,
|
||||
void __user *argp)
|
||||
{
|
||||
struct btrfs_ioctl_get_subvol_rootref_args *rootrefs;
|
||||
struct btrfs_root_ref *rref;
|
||||
struct btrfs_root *root;
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_key key;
|
||||
struct extent_buffer *leaf;
|
||||
struct inode *inode;
|
||||
u64 objectid;
|
||||
int slot;
|
||||
int ret;
|
||||
@@ -3101,15 +3111,13 @@ static int btrfs_ioctl_get_subvol_rootref(struct file *file, void __user *argp)
|
||||
return PTR_ERR(rootrefs);
|
||||
}
|
||||
|
||||
inode = file_inode(file);
|
||||
root = BTRFS_I(inode)->root->fs_info->tree_root;
|
||||
objectid = BTRFS_I(inode)->root->root_key.objectid;
|
||||
|
||||
objectid = root->root_key.objectid;
|
||||
key.objectid = objectid;
|
||||
key.type = BTRFS_ROOT_REF_KEY;
|
||||
key.offset = rootrefs->min_treeid;
|
||||
found = 0;
|
||||
|
||||
root = root->fs_info->tree_root;
|
||||
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
@@ -3189,6 +3197,13 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
|
||||
int err = 0;
|
||||
bool destroy_parent = false;
|
||||
|
||||
/* We don't support snapshots with extent tree v2 yet. */
|
||||
if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) {
|
||||
btrfs_err(fs_info,
|
||||
"extent tree v2 doesn't support snapshot deletion yet");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (destroy_v2) {
|
||||
vol_args2 = memdup_user(arg, sizeof(*vol_args2));
|
||||
if (IS_ERR(vol_args2))
|
||||
@@ -3464,6 +3479,11 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) {
|
||||
btrfs_err(fs_info, "device add not supported on extent tree v2 yet");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_DEV_ADD)) {
|
||||
if (!btrfs_exclop_start_try_lock(fs_info, BTRFS_EXCLOP_DEV_ADD))
|
||||
return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
|
||||
@@ -3989,6 +4009,11 @@ static long btrfs_ioctl_scrub(struct file *file, void __user *arg)
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) {
|
||||
btrfs_err(fs_info, "scrub is not supported on extent tree v2 yet");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sa = memdup_user(arg, sizeof(*sa));
|
||||
if (IS_ERR(sa))
|
||||
return PTR_ERR(sa);
|
||||
@@ -4088,6 +4113,11 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info,
|
||||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) {
|
||||
btrfs_err(fs_info, "device replace not supported on extent tree v2 yet");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
p = memdup_user(arg, sizeof(*p));
|
||||
if (IS_ERR(p))
|
||||
return PTR_ERR(p);
|
||||
@@ -5149,7 +5179,7 @@ out_drop_write:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _btrfs_ioctl_send(struct file *file, void __user *argp, bool compat)
|
||||
static int _btrfs_ioctl_send(struct inode *inode, void __user *argp, bool compat)
|
||||
{
|
||||
struct btrfs_ioctl_send_args *arg;
|
||||
int ret;
|
||||
@@ -5179,11 +5209,194 @@ static int _btrfs_ioctl_send(struct file *file, void __user *argp, bool compat)
|
||||
if (IS_ERR(arg))
|
||||
return PTR_ERR(arg);
|
||||
}
|
||||
ret = btrfs_ioctl_send(file, arg);
|
||||
ret = btrfs_ioctl_send(inode, arg);
|
||||
kfree(arg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btrfs_ioctl_encoded_read(struct file *file, void __user *argp,
|
||||
bool compat)
|
||||
{
|
||||
struct btrfs_ioctl_encoded_io_args args = { 0 };
|
||||
size_t copy_end_kernel = offsetofend(struct btrfs_ioctl_encoded_io_args,
|
||||
flags);
|
||||
size_t copy_end;
|
||||
struct iovec iovstack[UIO_FASTIOV];
|
||||
struct iovec *iov = iovstack;
|
||||
struct iov_iter iter;
|
||||
loff_t pos;
|
||||
struct kiocb kiocb;
|
||||
ssize_t ret;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
ret = -EPERM;
|
||||
goto out_acct;
|
||||
}
|
||||
|
||||
if (compat) {
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
|
||||
struct btrfs_ioctl_encoded_io_args_32 args32;
|
||||
|
||||
copy_end = offsetofend(struct btrfs_ioctl_encoded_io_args_32,
|
||||
flags);
|
||||
if (copy_from_user(&args32, argp, copy_end)) {
|
||||
ret = -EFAULT;
|
||||
goto out_acct;
|
||||
}
|
||||
args.iov = compat_ptr(args32.iov);
|
||||
args.iovcnt = args32.iovcnt;
|
||||
args.offset = args32.offset;
|
||||
args.flags = args32.flags;
|
||||
#else
|
||||
return -ENOTTY;
|
||||
#endif
|
||||
} else {
|
||||
copy_end = copy_end_kernel;
|
||||
if (copy_from_user(&args, argp, copy_end)) {
|
||||
ret = -EFAULT;
|
||||
goto out_acct;
|
||||
}
|
||||
}
|
||||
if (args.flags != 0) {
|
||||
ret = -EINVAL;
|
||||
goto out_acct;
|
||||
}
|
||||
|
||||
ret = import_iovec(READ, args.iov, args.iovcnt, ARRAY_SIZE(iovstack),
|
||||
&iov, &iter);
|
||||
if (ret < 0)
|
||||
goto out_acct;
|
||||
|
||||
if (iov_iter_count(&iter) == 0) {
|
||||
ret = 0;
|
||||
goto out_iov;
|
||||
}
|
||||
pos = args.offset;
|
||||
ret = rw_verify_area(READ, file, &pos, args.len);
|
||||
if (ret < 0)
|
||||
goto out_iov;
|
||||
|
||||
init_sync_kiocb(&kiocb, file);
|
||||
kiocb.ki_pos = pos;
|
||||
|
||||
ret = btrfs_encoded_read(&kiocb, &iter, &args);
|
||||
if (ret >= 0) {
|
||||
fsnotify_access(file);
|
||||
if (copy_to_user(argp + copy_end,
|
||||
(char *)&args + copy_end_kernel,
|
||||
sizeof(args) - copy_end_kernel))
|
||||
ret = -EFAULT;
|
||||
}
|
||||
|
||||
out_iov:
|
||||
kfree(iov);
|
||||
out_acct:
|
||||
if (ret > 0)
|
||||
add_rchar(current, ret);
|
||||
inc_syscr(current);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int btrfs_ioctl_encoded_write(struct file *file, void __user *argp, bool compat)
|
||||
{
|
||||
struct btrfs_ioctl_encoded_io_args args;
|
||||
struct iovec iovstack[UIO_FASTIOV];
|
||||
struct iovec *iov = iovstack;
|
||||
struct iov_iter iter;
|
||||
loff_t pos;
|
||||
struct kiocb kiocb;
|
||||
ssize_t ret;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
ret = -EPERM;
|
||||
goto out_acct;
|
||||
}
|
||||
|
||||
if (!(file->f_mode & FMODE_WRITE)) {
|
||||
ret = -EBADF;
|
||||
goto out_acct;
|
||||
}
|
||||
|
||||
if (compat) {
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
|
||||
struct btrfs_ioctl_encoded_io_args_32 args32;
|
||||
|
||||
if (copy_from_user(&args32, argp, sizeof(args32))) {
|
||||
ret = -EFAULT;
|
||||
goto out_acct;
|
||||
}
|
||||
args.iov = compat_ptr(args32.iov);
|
||||
args.iovcnt = args32.iovcnt;
|
||||
args.offset = args32.offset;
|
||||
args.flags = args32.flags;
|
||||
args.len = args32.len;
|
||||
args.unencoded_len = args32.unencoded_len;
|
||||
args.unencoded_offset = args32.unencoded_offset;
|
||||
args.compression = args32.compression;
|
||||
args.encryption = args32.encryption;
|
||||
memcpy(args.reserved, args32.reserved, sizeof(args.reserved));
|
||||
#else
|
||||
return -ENOTTY;
|
||||
#endif
|
||||
} else {
|
||||
if (copy_from_user(&args, argp, sizeof(args))) {
|
||||
ret = -EFAULT;
|
||||
goto out_acct;
|
||||
}
|
||||
}
|
||||
|
||||
ret = -EINVAL;
|
||||
if (args.flags != 0)
|
||||
goto out_acct;
|
||||
if (memchr_inv(args.reserved, 0, sizeof(args.reserved)))
|
||||
goto out_acct;
|
||||
if (args.compression == BTRFS_ENCODED_IO_COMPRESSION_NONE &&
|
||||
args.encryption == BTRFS_ENCODED_IO_ENCRYPTION_NONE)
|
||||
goto out_acct;
|
||||
if (args.compression >= BTRFS_ENCODED_IO_COMPRESSION_TYPES ||
|
||||
args.encryption >= BTRFS_ENCODED_IO_ENCRYPTION_TYPES)
|
||||
goto out_acct;
|
||||
if (args.unencoded_offset > args.unencoded_len)
|
||||
goto out_acct;
|
||||
if (args.len > args.unencoded_len - args.unencoded_offset)
|
||||
goto out_acct;
|
||||
|
||||
ret = import_iovec(WRITE, args.iov, args.iovcnt, ARRAY_SIZE(iovstack),
|
||||
&iov, &iter);
|
||||
if (ret < 0)
|
||||
goto out_acct;
|
||||
|
||||
file_start_write(file);
|
||||
|
||||
if (iov_iter_count(&iter) == 0) {
|
||||
ret = 0;
|
||||
goto out_end_write;
|
||||
}
|
||||
pos = args.offset;
|
||||
ret = rw_verify_area(WRITE, file, &pos, args.len);
|
||||
if (ret < 0)
|
||||
goto out_end_write;
|
||||
|
||||
init_sync_kiocb(&kiocb, file);
|
||||
ret = kiocb_set_rw_flags(&kiocb, 0);
|
||||
if (ret)
|
||||
goto out_end_write;
|
||||
kiocb.ki_pos = pos;
|
||||
|
||||
ret = btrfs_do_write_iter(&kiocb, &iter, &args);
|
||||
if (ret > 0)
|
||||
fsnotify_modify(file);
|
||||
|
||||
out_end_write:
|
||||
file_end_write(file);
|
||||
kfree(iov);
|
||||
out_acct:
|
||||
if (ret > 0)
|
||||
add_wchar(current, ret);
|
||||
inc_syscw(current);
|
||||
return ret;
|
||||
}
|
||||
|
||||
long btrfs_ioctl(struct file *file, unsigned int
|
||||
cmd, unsigned long arg)
|
||||
{
|
||||
@@ -5194,7 +5407,7 @@ long btrfs_ioctl(struct file *file, unsigned int
|
||||
|
||||
switch (cmd) {
|
||||
case FS_IOC_GETVERSION:
|
||||
return btrfs_ioctl_getversion(file, argp);
|
||||
return btrfs_ioctl_getversion(inode, argp);
|
||||
case FS_IOC_GETFSLABEL:
|
||||
return btrfs_ioctl_get_fslabel(fs_info, argp);
|
||||
case FS_IOC_SETFSLABEL:
|
||||
@@ -5214,7 +5427,7 @@ long btrfs_ioctl(struct file *file, unsigned int
|
||||
case BTRFS_IOC_SNAP_DESTROY_V2:
|
||||
return btrfs_ioctl_snap_destroy(file, argp, true);
|
||||
case BTRFS_IOC_SUBVOL_GETFLAGS:
|
||||
return btrfs_ioctl_subvol_getflags(file, argp);
|
||||
return btrfs_ioctl_subvol_getflags(inode, argp);
|
||||
case BTRFS_IOC_SUBVOL_SETFLAGS:
|
||||
return btrfs_ioctl_subvol_setflags(file, argp);
|
||||
case BTRFS_IOC_DEFAULT_SUBVOL:
|
||||
@@ -5238,11 +5451,11 @@ long btrfs_ioctl(struct file *file, unsigned int
|
||||
case BTRFS_IOC_BALANCE:
|
||||
return btrfs_ioctl_balance(file, NULL);
|
||||
case BTRFS_IOC_TREE_SEARCH:
|
||||
return btrfs_ioctl_tree_search(file, argp);
|
||||
return btrfs_ioctl_tree_search(inode, argp);
|
||||
case BTRFS_IOC_TREE_SEARCH_V2:
|
||||
return btrfs_ioctl_tree_search_v2(file, argp);
|
||||
return btrfs_ioctl_tree_search_v2(inode, argp);
|
||||
case BTRFS_IOC_INO_LOOKUP:
|
||||
return btrfs_ioctl_ino_lookup(file, argp);
|
||||
return btrfs_ioctl_ino_lookup(root, argp);
|
||||
case BTRFS_IOC_INO_PATHS:
|
||||
return btrfs_ioctl_ino_to_path(root, argp);
|
||||
case BTRFS_IOC_LOGICAL_INO:
|
||||
@@ -5289,10 +5502,10 @@ long btrfs_ioctl(struct file *file, unsigned int
|
||||
return btrfs_ioctl_set_received_subvol_32(file, argp);
|
||||
#endif
|
||||
case BTRFS_IOC_SEND:
|
||||
return _btrfs_ioctl_send(file, argp, false);
|
||||
return _btrfs_ioctl_send(inode, argp, false);
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
|
||||
case BTRFS_IOC_SEND_32:
|
||||
return _btrfs_ioctl_send(file, argp, true);
|
||||
return _btrfs_ioctl_send(inode, argp, true);
|
||||
#endif
|
||||
case BTRFS_IOC_GET_DEV_STATS:
|
||||
return btrfs_ioctl_get_dev_stats(fs_info, argp);
|
||||
@@ -5319,15 +5532,25 @@ long btrfs_ioctl(struct file *file, unsigned int
|
||||
case BTRFS_IOC_SET_FEATURES:
|
||||
return btrfs_ioctl_set_features(file, argp);
|
||||
case BTRFS_IOC_GET_SUBVOL_INFO:
|
||||
return btrfs_ioctl_get_subvol_info(file, argp);
|
||||
return btrfs_ioctl_get_subvol_info(inode, argp);
|
||||
case BTRFS_IOC_GET_SUBVOL_ROOTREF:
|
||||
return btrfs_ioctl_get_subvol_rootref(file, argp);
|
||||
return btrfs_ioctl_get_subvol_rootref(root, argp);
|
||||
case BTRFS_IOC_INO_LOOKUP_USER:
|
||||
return btrfs_ioctl_ino_lookup_user(file, argp);
|
||||
case FS_IOC_ENABLE_VERITY:
|
||||
return fsverity_ioctl_enable(file, (const void __user *)argp);
|
||||
case FS_IOC_MEASURE_VERITY:
|
||||
return fsverity_ioctl_measure(file, argp);
|
||||
case BTRFS_IOC_ENCODED_READ:
|
||||
return btrfs_ioctl_encoded_read(file, argp, false);
|
||||
case BTRFS_IOC_ENCODED_WRITE:
|
||||
return btrfs_ioctl_encoded_write(file, argp, false);
|
||||
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
|
||||
case BTRFS_IOC_ENCODED_READ_32:
|
||||
return btrfs_ioctl_encoded_read(file, argp, true);
|
||||
case BTRFS_IOC_ENCODED_WRITE_32:
|
||||
return btrfs_ioctl_encoded_write(file, argp, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
return -ENOTTY;
|
||||
|
||||
+7
-4
@@ -55,6 +55,9 @@
|
||||
* 0x1000 | SegHdr N+1| Data payload N+1 ... |
|
||||
*/
|
||||
|
||||
#define WORKSPACE_BUF_LENGTH (lzo1x_worst_compress(PAGE_SIZE))
|
||||
#define WORKSPACE_CBUF_LENGTH (lzo1x_worst_compress(PAGE_SIZE))
|
||||
|
||||
struct workspace {
|
||||
void *mem;
|
||||
void *buf; /* where decompressed data goes */
|
||||
@@ -83,8 +86,8 @@ struct list_head *lzo_alloc_workspace(unsigned int level)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
workspace->mem = kvmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
|
||||
workspace->buf = kvmalloc(lzo1x_worst_compress(PAGE_SIZE), GFP_KERNEL);
|
||||
workspace->cbuf = kvmalloc(lzo1x_worst_compress(PAGE_SIZE), GFP_KERNEL);
|
||||
workspace->buf = kvmalloc(WORKSPACE_BUF_LENGTH, GFP_KERNEL);
|
||||
workspace->cbuf = kvmalloc(WORKSPACE_CBUF_LENGTH, GFP_KERNEL);
|
||||
if (!workspace->mem || !workspace->buf || !workspace->cbuf)
|
||||
goto fail;
|
||||
|
||||
@@ -380,7 +383,7 @@ int lzo_decompress_bio(struct list_head *ws, struct compressed_bio *cb)
|
||||
kunmap(cur_page);
|
||||
cur_in += LZO_LEN;
|
||||
|
||||
if (seg_len > lzo1x_worst_compress(PAGE_SIZE)) {
|
||||
if (seg_len > WORKSPACE_CBUF_LENGTH) {
|
||||
/*
|
||||
* seg_len shouldn't be larger than we have allocated
|
||||
* for workspace->cbuf
|
||||
@@ -433,7 +436,7 @@ int lzo_decompress(struct list_head *ws, unsigned char *data_in,
|
||||
struct workspace *workspace = list_entry(ws, struct workspace, list);
|
||||
size_t in_len;
|
||||
size_t out_len;
|
||||
size_t max_segment_len = lzo1x_worst_compress(PAGE_SIZE);
|
||||
size_t max_segment_len = WORKSPACE_BUF_LENGTH;
|
||||
int ret = 0;
|
||||
char *kaddr;
|
||||
unsigned long bytes;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user