Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
337ccfce
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
337ccfce
编写于
1月 03, 2017
作者:
T
Takashi Iwai
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'for-linus' into for-next
上级
b0e159fe
6b7e95d1
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
310 addition
and
159 deletion
+310
-159
Documentation/DocBook/Makefile
Documentation/DocBook/Makefile
+1
-1
Documentation/unaligned-memory-access.txt
Documentation/unaligned-memory-access.txt
+1
-1
Makefile
Makefile
+1
-1
arch/x86/include/asm/bitops.h
arch/x86/include/asm/bitops.h
+13
-0
crypto/testmgr.c
crypto/testmgr.c
+28
-2
fs/dax.c
fs/dax.c
+154
-89
fs/ext2/inode.c
fs/ext2/inode.c
+1
-2
fs/ext4/file.c
fs/ext4/file.c
+10
-38
include/linux/dax.h
include/linux/dax.h
+3
-0
include/linux/page-flags.h
include/linux/page-flags.h
+1
-1
mm/filemap.c
mm/filemap.c
+31
-5
mm/truncate.c
mm/truncate.c
+61
-14
sound/firewire/amdtp-stream.c
sound/firewire/amdtp-stream.c
+1
-1
sound/firewire/amdtp-stream.h
sound/firewire/amdtp-stream.h
+2
-2
sound/firewire/fireworks/fireworks_stream.c
sound/firewire/fireworks/fireworks_stream.c
+1
-1
sound/firewire/tascam/tascam-stream.c
sound/firewire/tascam/tascam-stream.c
+1
-1
未找到文件。
Documentation/DocBook/Makefile
浏览文件 @
337ccfce
...
...
@@ -12,7 +12,7 @@ DOCBOOKS := z8530book.xml \
kernel-api.xml filesystems.xml lsm.xml kgdb.xml
\
gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml
\
genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml
\
80211.xml
sh.xml regulator.xml w1.xml
\
sh.xml regulator.xml w1.xml
\
writing_musb_glue_layer.xml iio.xml
ifeq
($(DOCBOOKS),)
...
...
Documentation/unaligned-memory-access.txt
浏览文件 @
337ccfce
...
...
@@ -151,7 +151,7 @@ bool ether_addr_equal(const u8 *addr1, const u8 *addr2)
#else
const u16 *a = (const u16 *)addr1;
const u16 *b = (const u16 *)addr2;
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]))
!
= 0;
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]))
=
= 0;
#endif
}
...
...
Makefile
浏览文件 @
337ccfce
VERSION
=
4
PATCHLEVEL
=
10
SUBLEVEL
=
0
EXTRAVERSION
=
-rc
1
EXTRAVERSION
=
-rc
2
NAME
=
Roaring Lionus
# *DOCUMENTATION*
...
...
arch/x86/include/asm/bitops.h
浏览文件 @
337ccfce
...
...
@@ -139,6 +139,19 @@ static __always_inline void __clear_bit(long nr, volatile unsigned long *addr)
asm
volatile
(
"btr %1,%0"
:
ADDR
:
"Ir"
(
nr
));
}
static
__always_inline
bool
clear_bit_unlock_is_negative_byte
(
long
nr
,
volatile
unsigned
long
*
addr
)
{
bool
negative
;
asm
volatile
(
LOCK_PREFIX
"andb %2,%1
\n\t
"
CC_SET
(
s
)
:
CC_OUT
(
s
)
(
negative
),
ADDR
:
"ir"
((
char
)
~
(
1
<<
nr
))
:
"memory"
);
return
negative
;
}
// Let everybody know we have it
#define clear_bit_unlock_is_negative_byte clear_bit_unlock_is_negative_byte
/*
* __clear_bit_unlock - Clears a bit in memory
* @nr: Bit to clear
...
...
crypto/testmgr.c
浏览文件 @
337ccfce
...
...
@@ -1461,16 +1461,25 @@ static int test_acomp(struct crypto_acomp *tfm, struct comp_testvec *ctemplate,
for
(
i
=
0
;
i
<
ctcount
;
i
++
)
{
unsigned
int
dlen
=
COMP_BUF_SIZE
;
int
ilen
=
ctemplate
[
i
].
inlen
;
void
*
input_vec
;
input_vec
=
kmalloc
(
ilen
,
GFP_KERNEL
);
if
(
!
input_vec
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
memcpy
(
input_vec
,
ctemplate
[
i
].
input
,
ilen
);
memset
(
output
,
0
,
dlen
);
init_completion
(
&
result
.
completion
);
sg_init_one
(
&
src
,
ctemplate
[
i
].
input
,
ilen
);
sg_init_one
(
&
src
,
input_vec
,
ilen
);
sg_init_one
(
&
dst
,
output
,
dlen
);
req
=
acomp_request_alloc
(
tfm
);
if
(
!
req
)
{
pr_err
(
"alg: acomp: request alloc failed for %s
\n
"
,
algo
);
kfree
(
input_vec
);
ret
=
-
ENOMEM
;
goto
out
;
}
...
...
@@ -1483,6 +1492,7 @@ static int test_acomp(struct crypto_acomp *tfm, struct comp_testvec *ctemplate,
if
(
ret
)
{
pr_err
(
"alg: acomp: compression failed on test %d for %s: ret=%d
\n
"
,
i
+
1
,
algo
,
-
ret
);
kfree
(
input_vec
);
acomp_request_free
(
req
);
goto
out
;
}
...
...
@@ -1491,6 +1501,7 @@ static int test_acomp(struct crypto_acomp *tfm, struct comp_testvec *ctemplate,
pr_err
(
"alg: acomp: Compression test %d failed for %s: output len = %d
\n
"
,
i
+
1
,
algo
,
req
->
dlen
);
ret
=
-
EINVAL
;
kfree
(
input_vec
);
acomp_request_free
(
req
);
goto
out
;
}
...
...
@@ -1500,26 +1511,37 @@ static int test_acomp(struct crypto_acomp *tfm, struct comp_testvec *ctemplate,
i
+
1
,
algo
);
hexdump
(
output
,
req
->
dlen
);
ret
=
-
EINVAL
;
kfree
(
input_vec
);
acomp_request_free
(
req
);
goto
out
;
}
kfree
(
input_vec
);
acomp_request_free
(
req
);
}
for
(
i
=
0
;
i
<
dtcount
;
i
++
)
{
unsigned
int
dlen
=
COMP_BUF_SIZE
;
int
ilen
=
dtemplate
[
i
].
inlen
;
void
*
input_vec
;
input_vec
=
kmalloc
(
ilen
,
GFP_KERNEL
);
if
(
!
input_vec
)
{
ret
=
-
ENOMEM
;
goto
out
;
}
memcpy
(
input_vec
,
dtemplate
[
i
].
input
,
ilen
);
memset
(
output
,
0
,
dlen
);
init_completion
(
&
result
.
completion
);
sg_init_one
(
&
src
,
dtemplate
[
i
].
input
,
ilen
);
sg_init_one
(
&
src
,
input_vec
,
ilen
);
sg_init_one
(
&
dst
,
output
,
dlen
);
req
=
acomp_request_alloc
(
tfm
);
if
(
!
req
)
{
pr_err
(
"alg: acomp: request alloc failed for %s
\n
"
,
algo
);
kfree
(
input_vec
);
ret
=
-
ENOMEM
;
goto
out
;
}
...
...
@@ -1532,6 +1554,7 @@ static int test_acomp(struct crypto_acomp *tfm, struct comp_testvec *ctemplate,
if
(
ret
)
{
pr_err
(
"alg: acomp: decompression failed on test %d for %s: ret=%d
\n
"
,
i
+
1
,
algo
,
-
ret
);
kfree
(
input_vec
);
acomp_request_free
(
req
);
goto
out
;
}
...
...
@@ -1540,6 +1563,7 @@ static int test_acomp(struct crypto_acomp *tfm, struct comp_testvec *ctemplate,
pr_err
(
"alg: acomp: Decompression test %d failed for %s: output len = %d
\n
"
,
i
+
1
,
algo
,
req
->
dlen
);
ret
=
-
EINVAL
;
kfree
(
input_vec
);
acomp_request_free
(
req
);
goto
out
;
}
...
...
@@ -1549,10 +1573,12 @@ static int test_acomp(struct crypto_acomp *tfm, struct comp_testvec *ctemplate,
i
+
1
,
algo
);
hexdump
(
output
,
req
->
dlen
);
ret
=
-
EINVAL
;
kfree
(
input_vec
);
acomp_request_free
(
req
);
goto
out
;
}
kfree
(
input_vec
);
acomp_request_free
(
req
);
}
...
...
fs/dax.c
浏览文件 @
337ccfce
...
...
@@ -451,16 +451,37 @@ void dax_wake_mapping_entry_waiter(struct address_space *mapping,
__wake_up
(
wq
,
TASK_NORMAL
,
wake_all
?
0
:
1
,
&
key
);
}
static
int
__dax_invalidate_mapping_entry
(
struct
address_space
*
mapping
,
pgoff_t
index
,
bool
trunc
)
{
int
ret
=
0
;
void
*
entry
;
struct
radix_tree_root
*
page_tree
=
&
mapping
->
page_tree
;
spin_lock_irq
(
&
mapping
->
tree_lock
);
entry
=
get_unlocked_mapping_entry
(
mapping
,
index
,
NULL
);
if
(
!
entry
||
!
radix_tree_exceptional_entry
(
entry
))
goto
out
;
if
(
!
trunc
&&
(
radix_tree_tag_get
(
page_tree
,
index
,
PAGECACHE_TAG_DIRTY
)
||
radix_tree_tag_get
(
page_tree
,
index
,
PAGECACHE_TAG_TOWRITE
)))
goto
out
;
radix_tree_delete
(
page_tree
,
index
);
mapping
->
nrexceptional
--
;
ret
=
1
;
out:
put_unlocked_mapping_entry
(
mapping
,
index
,
entry
);
spin_unlock_irq
(
&
mapping
->
tree_lock
);
return
ret
;
}
/*
* Delete exceptional DAX entry at @index from @mapping. Wait for radix tree
* entry to get unlocked before deleting it.
*/
int
dax_delete_mapping_entry
(
struct
address_space
*
mapping
,
pgoff_t
index
)
{
void
*
entry
;
int
ret
=
__dax_invalidate_mapping_entry
(
mapping
,
index
,
true
)
;
spin_lock_irq
(
&
mapping
->
tree_lock
);
entry
=
get_unlocked_mapping_entry
(
mapping
,
index
,
NULL
);
/*
* This gets called from truncate / punch_hole path. As such, the caller
* must hold locks protecting against concurrent modifications of the
...
...
@@ -468,16 +489,46 @@ int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index)
* caller has seen exceptional entry for this index, we better find it
* at that index as well...
*/
if
(
WARN_ON_ONCE
(
!
entry
||
!
radix_tree_exceptional_entry
(
entry
)))
{
spin_unlock_irq
(
&
mapping
->
tree_lock
);
return
0
;
}
radix_tree_delete
(
&
mapping
->
page_tree
,
index
);
WARN_ON_ONCE
(
!
ret
);
return
ret
;
}
/*
* Invalidate exceptional DAX entry if easily possible. This handles DAX
* entries for invalidate_inode_pages() so we evict the entry only if we can
* do so without blocking.
*/
int
dax_invalidate_mapping_entry
(
struct
address_space
*
mapping
,
pgoff_t
index
)
{
int
ret
=
0
;
void
*
entry
,
**
slot
;
struct
radix_tree_root
*
page_tree
=
&
mapping
->
page_tree
;
spin_lock_irq
(
&
mapping
->
tree_lock
);
entry
=
__radix_tree_lookup
(
page_tree
,
index
,
NULL
,
&
slot
);
if
(
!
entry
||
!
radix_tree_exceptional_entry
(
entry
)
||
slot_locked
(
mapping
,
slot
))
goto
out
;
if
(
radix_tree_tag_get
(
page_tree
,
index
,
PAGECACHE_TAG_DIRTY
)
||
radix_tree_tag_get
(
page_tree
,
index
,
PAGECACHE_TAG_TOWRITE
))
goto
out
;
radix_tree_delete
(
page_tree
,
index
);
mapping
->
nrexceptional
--
;
ret
=
1
;
out:
spin_unlock_irq
(
&
mapping
->
tree_lock
);
dax_wake_mapping_entry_waiter
(
mapping
,
index
,
entry
,
true
);
if
(
ret
)
dax_wake_mapping_entry_waiter
(
mapping
,
index
,
entry
,
true
);
return
ret
;
}
return
1
;
/*
* Invalidate exceptional DAX entry if it is clean.
*/
int
dax_invalidate_mapping_entry_sync
(
struct
address_space
*
mapping
,
pgoff_t
index
)
{
return
__dax_invalidate_mapping_entry
(
mapping
,
index
,
false
);
}
/*
...
...
@@ -488,15 +539,16 @@ int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index)
* otherwise it will simply fall out of the page cache under memory
* pressure without ever having been dirtied.
*/
static
int
dax_load_hole
(
struct
address_space
*
mapping
,
void
*
entry
,
static
int
dax_load_hole
(
struct
address_space
*
mapping
,
void
*
*
entry
,
struct
vm_fault
*
vmf
)
{
struct
page
*
page
;
int
ret
;
/* Hole page already exists? Return it... */
if
(
!
radix_tree_exceptional_entry
(
entry
))
{
vmf
->
page
=
entry
;
return
VM_FAULT_LOCKED
;
if
(
!
radix_tree_exceptional_entry
(
*
entry
))
{
page
=
*
entry
;
goto
out
;
}
/* This will replace locked radix tree entry with a hole page */
...
...
@@ -504,8 +556,17 @@ static int dax_load_hole(struct address_space *mapping, void *entry,
vmf
->
gfp_mask
|
__GFP_ZERO
);
if
(
!
page
)
return
VM_FAULT_OOM
;
out:
vmf
->
page
=
page
;
return
VM_FAULT_LOCKED
;
ret
=
finish_fault
(
vmf
);
vmf
->
page
=
NULL
;
*
entry
=
page
;
if
(
!
ret
)
{
/* Grab reference for PTE that is now referencing the page */
get_page
(
page
);
return
VM_FAULT_NOPAGE
;
}
return
ret
;
}
static
int
copy_user_dax
(
struct
block_device
*
bdev
,
sector_t
sector
,
size_t
size
,
...
...
@@ -934,6 +995,17 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
if
(
WARN_ON_ONCE
(
iomap
->
type
!=
IOMAP_MAPPED
))
return
-
EIO
;
/*
* Write can allocate block for an area which has a hole page mapped
* into page tables. We have to tear down these mappings so that data
* written by write(2) is visible in mmap.
*/
if
((
iomap
->
flags
&
IOMAP_F_NEW
)
&&
inode
->
i_mapping
->
nrpages
)
{
invalidate_inode_pages2_range
(
inode
->
i_mapping
,
pos
>>
PAGE_SHIFT
,
(
end
-
1
)
>>
PAGE_SHIFT
);
}
while
(
pos
<
end
)
{
unsigned
offset
=
pos
&
(
PAGE_SIZE
-
1
);
struct
blk_dax_ctl
dax
=
{
0
};
...
...
@@ -992,23 +1064,6 @@ dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,
if
(
iov_iter_rw
(
iter
)
==
WRITE
)
flags
|=
IOMAP_WRITE
;
/*
* Yes, even DAX files can have page cache attached to them: A zeroed
* page is inserted into the pagecache when we have to serve a write
* fault on a hole. It should never be dirtied and can simply be
* dropped from the pagecache once we get real data for the page.
*
* XXX: This is racy against mmap, and there's nothing we can do about
* it. We'll eventually need to shift this down even further so that
* we can check if we allocated blocks over a hole first.
*/
if
(
mapping
->
nrpages
)
{
ret
=
invalidate_inode_pages2_range
(
mapping
,
pos
>>
PAGE_SHIFT
,
(
pos
+
iov_iter_count
(
iter
)
-
1
)
>>
PAGE_SHIFT
);
WARN_ON_ONCE
(
ret
);
}
while
(
iov_iter_count
(
iter
))
{
ret
=
iomap_apply
(
inode
,
pos
,
iov_iter_count
(
iter
),
flags
,
ops
,
iter
,
dax_iomap_actor
);
...
...
@@ -1023,6 +1078,15 @@ dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,
}
EXPORT_SYMBOL_GPL
(
dax_iomap_rw
);
static
int
dax_fault_return
(
int
error
)
{
if
(
error
==
0
)
return
VM_FAULT_NOPAGE
;
if
(
error
==
-
ENOMEM
)
return
VM_FAULT_OOM
;
return
VM_FAULT_SIGBUS
;
}
/**
* dax_iomap_fault - handle a page fault on a DAX file
* @vma: The virtual memory area where the fault occurred
...
...
@@ -1055,12 +1119,6 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
if
(
pos
>=
i_size_read
(
inode
))
return
VM_FAULT_SIGBUS
;
entry
=
grab_mapping_entry
(
mapping
,
vmf
->
pgoff
,
0
);
if
(
IS_ERR
(
entry
))
{
error
=
PTR_ERR
(
entry
);
goto
out
;
}
if
((
vmf
->
flags
&
FAULT_FLAG_WRITE
)
&&
!
vmf
->
cow_page
)
flags
|=
IOMAP_WRITE
;
...
...
@@ -1071,9 +1129,15 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
*/
error
=
ops
->
iomap_begin
(
inode
,
pos
,
PAGE_SIZE
,
flags
,
&
iomap
);
if
(
error
)
goto
unlock_entry
;
return
dax_fault_return
(
error
)
;
if
(
WARN_ON_ONCE
(
iomap
.
offset
+
iomap
.
length
<
pos
+
PAGE_SIZE
))
{
error
=
-
EIO
;
/* fs corruption? */
vmf_ret
=
dax_fault_return
(
-
EIO
);
/* fs corruption? */
goto
finish_iomap
;
}
entry
=
grab_mapping_entry
(
mapping
,
vmf
->
pgoff
,
0
);
if
(
IS_ERR
(
entry
))
{
vmf_ret
=
dax_fault_return
(
PTR_ERR
(
entry
));
goto
finish_iomap
;
}
...
...
@@ -1096,13 +1160,13 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
}
if
(
error
)
goto
finish_iomap
;
goto
error_unlock_entry
;
__SetPageUptodate
(
vmf
->
cow_page
);
vmf_ret
=
finish_fault
(
vmf
);
if
(
!
vmf_ret
)
vmf_ret
=
VM_FAULT_DONE_COW
;
goto
finish_iomap
;
goto
unlock_entry
;
}
switch
(
iomap
.
type
)
{
...
...
@@ -1114,12 +1178,15 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
}
error
=
dax_insert_mapping
(
mapping
,
iomap
.
bdev
,
sector
,
PAGE_SIZE
,
&
entry
,
vma
,
vmf
);
/* -EBUSY is fine, somebody else faulted on the same PTE */
if
(
error
==
-
EBUSY
)
error
=
0
;
break
;
case
IOMAP_UNWRITTEN
:
case
IOMAP_HOLE
:
if
(
!
(
vmf
->
flags
&
FAULT_FLAG_WRITE
))
{
vmf_ret
=
dax_load_hole
(
mapping
,
entry
,
vmf
);
break
;
vmf_ret
=
dax_load_hole
(
mapping
,
&
entry
,
vmf
);
goto
unlock_entry
;
}
/*FALLTHRU*/
default:
...
...
@@ -1128,31 +1195,25 @@ int dax_iomap_fault(struct vm_area_struct *vma, struct vm_fault *vmf,
break
;
}
error_unlock_entry:
vmf_ret
=
dax_fault_return
(
error
)
|
major
;
unlock_entry:
put_locked_mapping_entry
(
mapping
,
vmf
->
pgoff
,
entry
);
finish_iomap:
if
(
ops
->
iomap_end
)
{
if
(
error
||
(
vmf_ret
&
VM_FAULT_ERROR
))
{
/* keep previous error */
ops
->
iomap_end
(
inode
,
pos
,
PAGE_SIZE
,
0
,
flags
,
&
iomap
);
}
else
{
error
=
ops
->
iomap_end
(
inode
,
pos
,
PAGE_SIZE
,
PAGE_SIZE
,
flags
,
&
iomap
);
}
}
unlock_entry:
if
(
vmf_ret
!=
VM_FAULT_LOCKED
||
error
)
put_locked_mapping_entry
(
mapping
,
vmf
->
pgoff
,
entry
);
out:
if
(
error
==
-
ENOMEM
)
return
VM_FAULT_OOM
|
major
;
/* -EBUSY is fine, somebody else faulted on the same PTE */
if
(
error
<
0
&&
error
!=
-
EBUSY
)
return
VM_FAULT_SIGBUS
|
major
;
if
(
vmf_ret
)
{
WARN_ON_ONCE
(
error
);
/* -EBUSY from ops->iomap_end? */
return
vmf_ret
;
int
copied
=
PAGE_SIZE
;
if
(
vmf_ret
&
VM_FAULT_ERROR
)
copied
=
0
;
/*
* The fault is done by now and there's no way back (other
* thread may be already happily using PTE we have installed).
* Just ignore error from ->iomap_end since we cannot do much
* with it.
*/
ops
->
iomap_end
(
inode
,
pos
,
PAGE_SIZE
,
copied
,
flags
,
&
iomap
);
}
return
VM_FAULT_NOPAGE
|
major
;
return
vmf_ret
;
}
EXPORT_SYMBOL_GPL
(
dax_iomap_fault
);
...
...
@@ -1276,16 +1337,6 @@ int dax_iomap_pmd_fault(struct vm_area_struct *vma, unsigned long address,
if
((
pgoff
|
PG_PMD_COLOUR
)
>
max_pgoff
)
goto
fallback
;
/*
* grab_mapping_entry() will make sure we get a 2M empty entry, a DAX
* PMD or a HZP entry. If it can't (because a 4k page is already in
* the tree, for instance), it will return -EEXIST and we just fall
* back to 4k entries.
*/
entry
=
grab_mapping_entry
(
mapping
,
pgoff
,
RADIX_DAX_PMD
);
if
(
IS_ERR
(
entry
))
goto
fallback
;
/*
* Note that we don't use iomap_apply here. We aren't doing I/O, only
* setting up a mapping, so really we're using iomap_begin() as a way
...
...
@@ -1294,10 +1345,21 @@ int dax_iomap_pmd_fault(struct vm_area_struct *vma, unsigned long address,
pos
=
(
loff_t
)
pgoff
<<
PAGE_SHIFT
;
error
=
ops
->
iomap_begin
(
inode
,
pos
,
PMD_SIZE
,
iomap_flags
,
&
iomap
);
if
(
error
)
goto
unlock_entry
;
goto
fallback
;
if
(
iomap
.
offset
+
iomap
.
length
<
pos
+
PMD_SIZE
)
goto
finish_iomap
;
/*
* grab_mapping_entry() will make sure we get a 2M empty entry, a DAX
* PMD or a HZP entry. If it can't (because a 4k page is already in
* the tree, for instance), it will return -EEXIST and we just fall
* back to 4k entries.
*/
entry
=
grab_mapping_entry
(
mapping
,
pgoff
,
RADIX_DAX_PMD
);
if
(
IS_ERR
(
entry
))
goto
finish_iomap
;
vmf
.
pgoff
=
pgoff
;
vmf
.
flags
=
flags
;
vmf
.
gfp_mask
=
mapping_gfp_mask
(
mapping
)
|
__GFP_IO
;
...
...
@@ -1310,7 +1372,7 @@ int dax_iomap_pmd_fault(struct vm_area_struct *vma, unsigned long address,
case
IOMAP_UNWRITTEN
:
case
IOMAP_HOLE
:
if
(
WARN_ON_ONCE
(
write
))
goto
finish_iomap
;
goto
unlock_entry
;
result
=
dax_pmd_load_hole
(
vma
,
pmd
,
&
vmf
,
address
,
&
iomap
,
&
entry
);
break
;
...
...
@@ -1319,20 +1381,23 @@ int dax_iomap_pmd_fault(struct vm_area_struct *vma, unsigned long address,
break
;
}
unlock_entry:
put_locked_mapping_entry
(
mapping
,
pgoff
,
entry
);
finish_iomap:
if
(
ops
->
iomap_end
)
{
if
(
result
==
VM_FAULT_FALLBACK
)
{
ops
->
iomap_end
(
inode
,
pos
,
PMD_SIZE
,
0
,
iomap_flags
,
&
iomap
);
}
else
{
error
=
ops
->
iomap_end
(
inode
,
pos
,
PMD_SIZE
,
PMD_SIZE
,
iomap_flags
,
&
iomap
);
if
(
error
)
result
=
VM_FAULT_FALLBACK
;
}
int
copied
=
PMD_SIZE
;
if
(
result
==
VM_FAULT_FALLBACK
)
copied
=
0
;
/*
* The fault is done by now and there's no way back (other
* thread may be already happily using PMD we have installed).
* Just ignore error from ->iomap_end since we cannot do much
* with it.
*/
ops
->
iomap_end
(
inode
,
pos
,
PMD_SIZE
,
copied
,
iomap_flags
,
&
iomap
);
}
unlock_entry:
put_locked_mapping_entry
(
mapping
,
pgoff
,
entry
);
fallback:
if
(
result
==
VM_FAULT_FALLBACK
)
{
split_huge_pmd
(
vma
,
pmd
,
address
);
...
...
fs/ext2/inode.c
浏览文件 @
337ccfce
...
...
@@ -751,9 +751,8 @@ static int ext2_get_blocks(struct inode *inode,
mutex_unlock
(
&
ei
->
truncate_mutex
);
goto
cleanup
;
}
}
else
{
*
new
=
true
;
}
*
new
=
true
;
ext2_splice_branch
(
inode
,
iblock
,
partial
,
indirect_blks
,
count
);
mutex_unlock
(
&
ei
->
truncate_mutex
);
...
...
fs/ext4/file.c
浏览文件 @
337ccfce
...
...
@@ -258,7 +258,6 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
static
int
ext4_dax_fault
(
struct
vm_area_struct
*
vma
,
struct
vm_fault
*
vmf
)
{
int
result
;
handle_t
*
handle
=
NULL
;
struct
inode
*
inode
=
file_inode
(
vma
->
vm_file
);
struct
super_block
*
sb
=
inode
->
i_sb
;
bool
write
=
vmf
->
flags
&
FAULT_FLAG_WRITE
;
...
...
@@ -266,24 +265,12 @@ static int ext4_dax_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
if
(
write
)
{
sb_start_pagefault
(
sb
);
file_update_time
(
vma
->
vm_file
);
down_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
handle
=
ext4_journal_start_sb
(
sb
,
EXT4_HT_WRITE_PAGE
,
EXT4_DATA_TRANS_BLOCKS
(
sb
));
}
else
down_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
if
(
IS_ERR
(
handle
))
result
=
VM_FAULT_SIGBUS
;
else
result
=
dax_iomap_fault
(
vma
,
vmf
,
&
ext4_iomap_ops
);
if
(
write
)
{
if
(
!
IS_ERR
(
handle
))
ext4_journal_stop
(
handle
);
up_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
}
down_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
result
=
dax_iomap_fault
(
vma
,
vmf
,
&
ext4_iomap_ops
);
up_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
if
(
write
)
sb_end_pagefault
(
sb
);
}
else
up_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
return
result
;
}
...
...
@@ -292,7 +279,6 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr,
pmd_t
*
pmd
,
unsigned
int
flags
)
{
int
result
;
handle_t
*
handle
=
NULL
;
struct
inode
*
inode
=
file_inode
(
vma
->
vm_file
);
struct
super_block
*
sb
=
inode
->
i_sb
;
bool
write
=
flags
&
FAULT_FLAG_WRITE
;
...
...
@@ -300,27 +286,13 @@ static int ext4_dax_pmd_fault(struct vm_area_struct *vma, unsigned long addr,
if
(
write
)
{
sb_start_pagefault
(
sb
);
file_update_time
(
vma
->
vm_file
);
down_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
handle
=
ext4_journal_start_sb
(
sb
,
EXT4_HT_WRITE_PAGE
,
ext4_chunk_trans_blocks
(
inode
,
PMD_SIZE
/
PAGE_SIZE
));
}
else
down_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
if
(
IS_ERR
(
handle
))
result
=
VM_FAULT_SIGBUS
;
else
{
result
=
dax_iomap_pmd_fault
(
vma
,
addr
,
pmd
,
flags
,
&
ext4_iomap_ops
);
}
if
(
write
)
{
if
(
!
IS_ERR
(
handle
))
ext4_journal_stop
(
handle
);
up_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
down_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
result
=
dax_iomap_pmd_fault
(
vma
,
addr
,
pmd
,
flags
,
&
ext4_iomap_ops
);
up_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
if
(
write
)
sb_end_pagefault
(
sb
);
}
else
up_read
(
&
EXT4_I
(
inode
)
->
i_mmap_sem
);
return
result
;
}
...
...
include/linux/dax.h
浏览文件 @
337ccfce
...
...
@@ -41,6 +41,9 @@ ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,
int
dax_iomap_fault
(
struct
vm_area_struct
*
vma
,
struct
vm_fault
*
vmf
,
struct
iomap_ops
*
ops
);
int
dax_delete_mapping_entry
(
struct
address_space
*
mapping
,
pgoff_t
index
);
int
dax_invalidate_mapping_entry
(
struct
address_space
*
mapping
,
pgoff_t
index
);
int
dax_invalidate_mapping_entry_sync
(
struct
address_space
*
mapping
,
pgoff_t
index
);
void
dax_wake_mapping_entry_waiter
(
struct
address_space
*
mapping
,
pgoff_t
index
,
void
*
entry
,
bool
wake_all
);
...
...
include/linux/page-flags.h
浏览文件 @
337ccfce
...
...
@@ -73,13 +73,13 @@
*/
enum
pageflags
{
PG_locked
,
/* Page is locked. Don't touch. */
PG_waiters
,
/* Page has waiters, check its waitqueue */
PG_error
,
PG_referenced
,
PG_uptodate
,
PG_dirty
,
PG_lru
,
PG_active
,
PG_waiters
,
/* Page has waiters, check its waitqueue. Must be bit #7 and in the same byte as "PG_locked" */
PG_slab
,
PG_owner_priv_1
,
/* Owner use. If pagecache, fs may use*/
PG_arch_1
,
...
...
mm/filemap.c
浏览文件 @
337ccfce
...
...
@@ -912,6 +912,29 @@ void add_page_wait_queue(struct page *page, wait_queue_t *waiter)
}
EXPORT_SYMBOL_GPL
(
add_page_wait_queue
);
#ifndef clear_bit_unlock_is_negative_byte
/*
* PG_waiters is the high bit in the same byte as PG_lock.
*
* On x86 (and on many other architectures), we can clear PG_lock and
* test the sign bit at the same time. But if the architecture does
* not support that special operation, we just do this all by hand
* instead.
*
* The read of PG_waiters has to be after (or concurrently with) PG_locked
* being cleared, but a memory barrier should be unneccssary since it is
* in the same byte as PG_locked.
*/
static
inline
bool
clear_bit_unlock_is_negative_byte
(
long
nr
,
volatile
void
*
mem
)
{
clear_bit_unlock
(
nr
,
mem
);
/* smp_mb__after_atomic(); */
return
test_bit
(
PG_waiters
,
mem
);
}
#endif
/**
* unlock_page - unlock a locked page
* @page: the page
...
...
@@ -921,16 +944,19 @@ EXPORT_SYMBOL_GPL(add_page_wait_queue);
* mechanism between PageLocked pages and PageWriteback pages is shared.
* But that's OK - sleepers in wait_on_page_writeback() just go back to sleep.
*
* The mb is necessary to enforce ordering between the clear_bit and the read
* of the waitqueue (to avoid SMP races with a parallel wait_on_page_locked()).
* Note that this depends on PG_waiters being the sign bit in the byte
* that contains PG_locked - thus the BUILD_BUG_ON(). That allows us to
* clear the PG_locked bit and test PG_waiters at the same time fairly
* portably (architectures that do LL/SC can test any bit, while x86 can
* test the sign bit).
*/
void
unlock_page
(
struct
page
*
page
)
{
BUILD_BUG_ON
(
PG_waiters
!=
7
);
page
=
compound_head
(
page
);
VM_BUG_ON_PAGE
(
!
PageLocked
(
page
),
page
);
clear_bit_unlock
(
PG_locked
,
&
page
->
flags
);
smp_mb__after_atomic
();
wake_up_page
(
page
,
PG_locked
);
if
(
clear_bit_unlock_is_negative_byte
(
PG_locked
,
&
page
->
flags
))
wake_up_page_bit
(
page
,
PG_locked
);
}
EXPORT_SYMBOL
(
unlock_page
);
...
...
mm/truncate.c
浏览文件 @
337ccfce
...
...
@@ -24,20 +24,12 @@
#include <linux/rmap.h>
#include "internal.h"
static
void
clear_
exceptional_entry
(
struct
address_space
*
mapping
,
pgoff_t
index
,
void
*
entry
)
static
void
clear_
shadow_entry
(
struct
address_space
*
mapping
,
pgoff_t
index
,
void
*
entry
)
{
struct
radix_tree_node
*
node
;
void
**
slot
;
/* Handled by shmem itself */
if
(
shmem_mapping
(
mapping
))
return
;
if
(
dax_mapping
(
mapping
))
{
dax_delete_mapping_entry
(
mapping
,
index
);
return
;
}
spin_lock_irq
(
&
mapping
->
tree_lock
);
/*
* Regular page slots are stabilized by the page lock even
...
...
@@ -55,6 +47,56 @@ static void clear_exceptional_entry(struct address_space *mapping,
spin_unlock_irq
(
&
mapping
->
tree_lock
);
}
/*
* Unconditionally remove exceptional entry. Usually called from truncate path.
*/
static
void
truncate_exceptional_entry
(
struct
address_space
*
mapping
,
pgoff_t
index
,
void
*
entry
)
{
/* Handled by shmem itself */
if
(
shmem_mapping
(
mapping
))
return
;
if
(
dax_mapping
(
mapping
))
{
dax_delete_mapping_entry
(
mapping
,
index
);
return
;
}
clear_shadow_entry
(
mapping
,
index
,
entry
);
}
/*
* Invalidate exceptional entry if easily possible. This handles exceptional
* entries for invalidate_inode_pages() so for DAX it evicts only unlocked and
* clean entries.
*/
static
int
invalidate_exceptional_entry
(
struct
address_space
*
mapping
,
pgoff_t
index
,
void
*
entry
)
{
/* Handled by shmem itself */
if
(
shmem_mapping
(
mapping
))
return
1
;
if
(
dax_mapping
(
mapping
))
return
dax_invalidate_mapping_entry
(
mapping
,
index
);
clear_shadow_entry
(
mapping
,
index
,
entry
);
return
1
;
}
/*
* Invalidate exceptional entry if clean. This handles exceptional entries for
* invalidate_inode_pages2() so for DAX it evicts only clean entries.
*/
static
int
invalidate_exceptional_entry2
(
struct
address_space
*
mapping
,
pgoff_t
index
,
void
*
entry
)
{
/* Handled by shmem itself */
if
(
shmem_mapping
(
mapping
))
return
1
;
if
(
dax_mapping
(
mapping
))
return
dax_invalidate_mapping_entry_sync
(
mapping
,
index
);
clear_shadow_entry
(
mapping
,
index
,
entry
);
return
1
;
}
/**
* do_invalidatepage - invalidate part or all of a page
* @page: the page which is affected
...
...
@@ -262,7 +304,8 @@ void truncate_inode_pages_range(struct address_space *mapping,
break
;
if
(
radix_tree_exceptional_entry
(
page
))
{
clear_exceptional_entry
(
mapping
,
index
,
page
);
truncate_exceptional_entry
(
mapping
,
index
,
page
);
continue
;
}
...
...
@@ -351,7 +394,8 @@ void truncate_inode_pages_range(struct address_space *mapping,
}
if
(
radix_tree_exceptional_entry
(
page
))
{
clear_exceptional_entry
(
mapping
,
index
,
page
);
truncate_exceptional_entry
(
mapping
,
index
,
page
);
continue
;
}
...
...
@@ -470,7 +514,8 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
break
;
if
(
radix_tree_exceptional_entry
(
page
))
{
clear_exceptional_entry
(
mapping
,
index
,
page
);
invalidate_exceptional_entry
(
mapping
,
index
,
page
);
continue
;
}
...
...
@@ -592,7 +637,9 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
break
;
if
(
radix_tree_exceptional_entry
(
page
))
{
clear_exceptional_entry
(
mapping
,
index
,
page
);
if
(
!
invalidate_exceptional_entry2
(
mapping
,
index
,
page
))
ret
=
-
EBUSY
;
continue
;
}
...
...
sound/firewire/amdtp-stream.c
浏览文件 @
337ccfce
...
...
@@ -69,7 +69,7 @@ static void pcm_period_tasklet(unsigned long data);
* @protocol_size: the size to allocate newly for protocol
*/
int
amdtp_stream_init
(
struct
amdtp_stream
*
s
,
struct
fw_unit
*
unit
,
enum
amdtp_stream_direction
dir
,
enum
cip_flags
flags
,
enum
amdtp_stream_direction
dir
,
int
flags
,
unsigned
int
fmt
,
amdtp_stream_process_data_blocks_t
process_data_blocks
,
unsigned
int
protocol_size
)
...
...
sound/firewire/amdtp-stream.h
浏览文件 @
337ccfce
...
...
@@ -93,7 +93,7 @@ typedef unsigned int (*amdtp_stream_process_data_blocks_t)(
unsigned
int
*
syt
);
struct
amdtp_stream
{
struct
fw_unit
*
unit
;
enum
cip_flags
flags
;
int
flags
;
enum
amdtp_stream_direction
direction
;
struct
mutex
mutex
;
...
...
@@ -137,7 +137,7 @@ struct amdtp_stream {
};
int
amdtp_stream_init
(
struct
amdtp_stream
*
s
,
struct
fw_unit
*
unit
,
enum
amdtp_stream_direction
dir
,
enum
cip_flags
flags
,
enum
amdtp_stream_direction
dir
,
int
flags
,
unsigned
int
fmt
,
amdtp_stream_process_data_blocks_t
process_data_blocks
,
unsigned
int
protocol_size
);
...
...
sound/firewire/fireworks/fireworks_stream.c
浏览文件 @
337ccfce
...
...
@@ -117,7 +117,7 @@ destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream)
conn
=
&
efw
->
in_conn
;
amdtp_stream_destroy
(
stream
);
cmp_connection_destroy
(
&
efw
->
out_
conn
);
cmp_connection_destroy
(
conn
);
}
static
int
...
...
sound/firewire/tascam/tascam-stream.c
浏览文件 @
337ccfce
...
...
@@ -343,7 +343,7 @@ int snd_tscm_stream_init_duplex(struct snd_tscm *tscm)
if
(
err
<
0
)
amdtp_stream_destroy
(
&
tscm
->
rx_stream
);
return
0
;
return
err
;
}
/* At bus reset, streaming is stopped and some registers are clear. */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录