Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
a6d938f4
Commit
a6d938f4
authored
Nov 23, 2007
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Import 2.1.51
parent
94520e42
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1085 additions
and
871 deletions
+1085
-871
Documentation/Configure.help
Documentation/Configure.help
+934
-673
arch/i386/mm/fault.c
arch/i386/mm/fault.c
+4
-5
drivers/char/uni_hash.tbl
drivers/char/uni_hash.tbl
+0
-89
fs/namei.c
fs/namei.c
+0
-12
fs/nfsd/export.c
fs/nfsd/export.c
+1
-1
fs/pipe.c
fs/pipe.c
+7
-2
fs/read_write.c
fs/read_write.c
+1
-1
fs/super.c
fs/super.c
+1
-3
include/linux/fs.h
include/linux/fs.h
+1
-1
include/linux/nfsd/nfsfh.h
include/linux/nfsd/nfsfh.h
+2
-0
kernel/fork.c
kernel/fork.c
+62
-44
mm/memory.c
mm/memory.c
+31
-15
mm/mmap.c
mm/mmap.c
+41
-25
No files found.
Documentation/Configure.help
View file @
a6d938f4
This source diff could not be displayed because it is too large. You can
view the blob
instead.
arch/i386/mm/fault.c
View file @
a6d938f4
...
...
@@ -186,16 +186,15 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
*
* First we check if it was the bootup rw-test, though..
*/
if
(
wp_works_ok
<
0
&&
address
==
0xc0000000
&&
(
error_code
&
1
))
{
if
(
wp_works_ok
<
0
&&
address
==
TASK_SIZE
&&
(
error_code
&
1
))
{
wp_works_ok
=
1
;
pg0
[
0
]
=
pte_val
(
mk_pte
(
0
,
PAGE_SHARED
));
pg0
[
0
]
=
pte_val
(
mk_pte
(
TASK_SIZE
,
PAGE_SHARED
));
flush_tlb
();
goto
out
;
}
if
(
address
<
PAGE_SIZE
)
{
if
(
address
<
PAGE_SIZE
)
printk
(
KERN_ALERT
"Unable to handle kernel NULL pointer dereference"
);
pg0
[
0
]
=
pte_val
(
mk_pte
(
0
,
PAGE_SHARED
));
}
else
else
printk
(
KERN_ALERT
"Unable to handle kernel paging request"
);
printk
(
" at virtual address %08lx
\n
"
,
address
);
__asm__
(
"movl %%cr3,%0"
:
"=r"
(
page
));
...
...
drivers/char/uni_hash.tbl
deleted
100644 → 0
View file @
94520e42
/*
* uni_hash.tbl
*
* Do not edit this file; it was automatically generated by
*
* conmakehash cp437.uni > uni_hash.tbl
*
*/
#include <linux/types.h>
#include <linux/kd.h>
static u8 dfont_unicount[256] =
{
1, 1, 1, 1, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 2, 1, 1, 1, 1, 1,
1, 1, 1, 1, 2, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 5, 1, 2, 1, 4, 1, 1,
1, 5, 1, 2, 1, 1, 1, 5,
1, 1, 2, 1, 1, 4, 1, 1,
1, 2, 1, 1, 1, 1, 1, 2,
1, 2, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 1, 1,
2, 2, 1, 1, 2, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 2, 1, 1, 1, 1, 2, 1,
2, 1, 2, 1, 1, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 2, 1
};
static u16 dfont_unitable[297] =
{
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x25c6, 0x2663, 0x2660,
0x2022, 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b,
0x263c, 0x25b6, 0x25ba, 0x25c0, 0x25c4, 0x2195, 0x203c, 0x00b6,
0x00a7, 0x25ac, 0x21a8, 0x2191, 0x2193, 0x2192, 0x2190, 0x221f,
0x2194, 0x25b2, 0x25bc, 0x0020, 0x0021, 0x0022, 0x00a8, 0x0023,
0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b,
0x002c, 0x00b8, 0x002d, 0x00ad, 0x002e, 0x002f, 0x0030, 0x0031,
0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039,
0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040, 0x0041,
0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x0042, 0x0043, 0x00a9, 0x0044,
0x0045, 0x00c8, 0x00ca, 0x00cb, 0x0046, 0x0047, 0x0048, 0x0049,
0x00cc, 0x00cd, 0x00ce, 0x00cf, 0x004a, 0x004b, 0x212a, 0x004c,
0x004d, 0x004e, 0x004f, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x0050,
0x0051, 0x0052, 0x00ae, 0x0053, 0x0054, 0x0055, 0x00d9, 0x00da,
0x00db, 0x0056, 0x0057, 0x0058, 0x0059, 0x00dd, 0x005a, 0x005b,
0x005c, 0x005d, 0x005e, 0x005f, 0xf804, 0x0060, 0x0061, 0x00e3,
0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, 0x00f5, 0x0070,
0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
0x00d7, 0x0079, 0x00fd, 0x007a, 0x007b, 0x007c, 0x00a5, 0x007d,
0x007e, 0x2302, 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0,
0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec,
0x00c4, 0x00c5, 0x212b, 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6,
0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3,
0x00a5, 0x20a7, 0x0192, 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1,
0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc,
0x00a1, 0x00ab, 0x00bb, 0x2591, 0x2592, 0x2593, 0x2502, 0x2524,
0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d,
0x255c, 0x255b, 0x2510, 0x2514, 0x2534, 0x252c, 0x251c, 0x2500,
0x253c, 0x255e, 0x255f, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560,
0x2550, 0x256c, 0x2567, 0x2568, 0x2564, 0x2565, 0x2559, 0x2558,
0x2552, 0x2553, 0x256b, 0x256a, 0x2518, 0x250c, 0x2588, 0x2584,
0x258c, 0x2590, 0x2580, 0x03b1, 0x03b2, 0x00df, 0x0393, 0x03c0,
0x03a3, 0x03c3, 0x00b5, 0x03bc, 0x03c4, 0x03a6, 0x00d8, 0x0398,
0x03a9, 0x2126, 0x03b4, 0x221e, 0x03c6, 0x00f8, 0x03b5, 0x2229,
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0xfffd,
0x00a0
};
\ No newline at end of file
fs/namei.c
View file @
a6d938f4
...
...
@@ -105,18 +105,6 @@ static inline char * get_page(void)
return
res
;
}
/*
* Kernel pointers have redundant information, so we can use a
* scheme where we can return either an error code or a dentry
* pointer with the same return value.
*
* This should be a per-architecture thing, to allow different
* error and pointer decisions.
*/
#define ERR_PTR(err) ((void *)((long)(err)))
#define PTR_ERR(ptr) ((long)(ptr))
#define IS_ERR(ptr) ((unsigned long)(ptr) > (unsigned long)(-1000))
inline
void
putname
(
char
*
name
)
{
if
(
name
)
{
...
...
fs/nfsd/export.c
View file @
a6d938f4
...
...
@@ -248,7 +248,7 @@ exp_export(struct nfsctl_export *nxp)
finish:
/* Release dentry */
if
(
err
<
0
&&
dentry
)
if
(
err
<
0
&&
!
IS_ERR
(
dentry
)
)
dput
(
dentry
);
/* Unlock hashtable */
...
...
fs/pipe.c
View file @
a6d938f4
...
...
@@ -399,7 +399,7 @@ static struct inode * get_pipe_inode(void)
/*
* Mark the inode dirty from the very beginning,
* that way it will never be moved to the dirty
* list because "ma
ke
_inode_dirty()" will think
* list because "ma
rk
_inode_dirty()" will think
* that it already _is_ on the dirty list.
*/
inode
->
i_state
=
1
<<
I_DIRTY
;
...
...
@@ -439,7 +439,7 @@ int do_pipe(int *fd)
int
error
;
int
i
,
j
;
error
=
ENFILE
;
error
=
-
ENFILE
;
f1
=
get_empty_filp
();
if
(
!
f1
)
goto
no_files
;
...
...
@@ -462,7 +462,10 @@ int do_pipe(int *fd)
goto
close_f12_inode_i
;
j
=
error
;
error
=
-
ENOMEM
;
f1
->
f_dentry
=
f2
->
f_dentry
=
dget
(
d_alloc_root
(
inode
,
NULL
));
if
(
!
f1
->
f_dentry
)
goto
close_f12_inode_i_j
;
/* read file */
f1
->
f_pos
=
f2
->
f_pos
=
0
;
...
...
@@ -480,6 +483,8 @@ int do_pipe(int *fd)
fd
[
1
]
=
j
;
return
0
;
close_f12_inode_i_j:
put_unused_fd
(
j
);
close_f12_inode_i:
put_unused_fd
(
i
);
close_f12_inode:
...
...
fs/read_write.c
View file @
a6d938f4
...
...
@@ -130,7 +130,7 @@ asmlinkage long sys_read(unsigned int fd, char * buf, unsigned long count)
goto
bad_file
;
dentry
=
file
->
f_dentry
;
if
(
!
dentry
)
goto
bad_file
;
goto
out
;
inode
=
dentry
->
d_inode
;
if
(
!
inode
)
goto
out
;
...
...
fs/super.c
View file @
a6d938f4
...
...
@@ -811,14 +811,12 @@ static int do_remount_sb(struct super_block *sb, int flags, char *data)
if
((
flags
&
MS_RDONLY
)
&&
!
(
sb
->
s_flags
&
MS_RDONLY
))
if
(
!
fs_may_remount_ro
(
sb
))
return
-
EBUSY
;
sb
->
s_flags
=
(
flags
&
~
MS_RDONLY
)
|
(
sb
->
s_flags
&
MS_RDONLY
);
if
(
sb
->
s_op
&&
sb
->
s_op
->
remount_fs
)
{
retval
=
sb
->
s_op
->
remount_fs
(
sb
,
&
flags
,
data
);
if
(
retval
)
return
retval
;
}
sb
->
s_flags
=
(
sb
->
s_flags
&
~
MS_RMT_MASK
)
|
(
flags
&
MS_RMT_MASK
);
sb
->
s_flags
=
(
sb
->
s_flags
&
~
MS_RMT_MASK
)
|
(
flags
&
MS_RMT_MASK
);
vfsmnt
=
lookup_vfsmnt
(
sb
->
s_dev
);
if
(
vfsmnt
)
vfsmnt
->
mnt_flags
=
sb
->
s_flags
;
...
...
include/linux/fs.h
View file @
a6d938f4
...
...
@@ -93,7 +93,7 @@ extern int max_files, nr_files;
/*
* Flags that can be altered by MS_REMOUNT
*/
#define MS_RMT_MASK (MS_RDONLY|MS_MANDLOCK)
#define MS_RMT_MASK (MS_RDONLY|MS_MANDLOCK
|MS_NOATIME
)
/*
* Magic mount flag number. Has to be or-ed to the flag values.
...
...
include/linux/nfsd/nfsfh.h
View file @
a6d938f4
...
...
@@ -137,6 +137,7 @@ fh_put(struct svc_fh *fhp)
if
(
fhp
->
fh_dverified
)
{
fh_unlock
(
fhp
);
dput
(
fhp
->
fh_handle
.
fh_dentry
);
fhp
->
fh_dverified
=
0
;
}
}
#else
...
...
@@ -159,6 +160,7 @@ __fh_put(struct svc_fh *fhp, char *file, int line)
}
else
{
fh_unlock
(
fhp
);
dput
(
dentry
);
fhp
->
fh_dverified
=
0
;
}
}
#endif
...
...
kernel/fork.c
View file @
a6d938f4
...
...
@@ -206,6 +206,7 @@ static int get_pid(unsigned long flags)
static
inline
int
dup_mmap
(
struct
mm_struct
*
mm
)
{
struct
vm_area_struct
*
mpnt
,
*
tmp
,
**
pprev
;
int
retval
;
mm
->
mmap
=
mm
->
mmap_cache
=
NULL
;
flush_cache_mm
(
current
->
mm
);
...
...
@@ -213,19 +214,17 @@ static inline int dup_mmap(struct mm_struct * mm)
for
(
mpnt
=
current
->
mm
->
mmap
;
mpnt
;
mpnt
=
mpnt
->
vm_next
)
{
struct
dentry
*
dentry
;
retval
=
-
ENOMEM
;
tmp
=
kmem_cache_alloc
(
vm_area_cachep
,
SLAB_KERNEL
);
if
(
!
tmp
)
{
exit_mmap
(
mm
);
flush_tlb_mm
(
current
->
mm
);
return
-
ENOMEM
;
}
if
(
!
tmp
)
goto
fail_nomem
;
*
tmp
=
*
mpnt
;
tmp
->
vm_flags
&=
~
VM_LOCKED
;
tmp
->
vm_mm
=
mm
;
tmp
->
vm_next
=
NULL
;
dentry
=
tmp
->
vm_dentry
;
if
(
dentry
)
{
d
entry
->
d_count
++
;
d
get
(
dentry
)
;
if
(
tmp
->
vm_flags
&
VM_DENYWRITE
)
dentry
->
d_inode
->
i_writecount
--
;
...
...
@@ -236,60 +235,79 @@ static inline int dup_mmap(struct mm_struct * mm)
mpnt
->
vm_next_share
=
tmp
;
tmp
->
vm_pprev_share
=
&
mpnt
->
vm_next_share
;
}
if
(
copy_page_range
(
mm
,
current
->
mm
,
tmp
))
{
exit_mmap
(
mm
);
flush_tlb_mm
(
current
->
mm
);
return
-
ENOMEM
;
}
if
(
tmp
->
vm_ops
&&
tmp
->
vm_ops
->
open
)
/* Copy the pages, but defer checking for errors */
retval
=
copy_page_range
(
mm
,
current
->
mm
,
tmp
);
if
(
!
retval
&&
tmp
->
vm_ops
&&
tmp
->
vm_ops
->
open
)
tmp
->
vm_ops
->
open
(
tmp
);
/* Ok, finally safe to link it in. */
/*
* Link in the new vma even if an error occurred,
* so that exit_mmap() can clean up the mess.
*/
if
((
tmp
->
vm_next
=
*
pprev
)
!=
NULL
)
(
*
pprev
)
->
vm_pprev
=
&
tmp
->
vm_next
;
*
pprev
=
tmp
;
tmp
->
vm_pprev
=
pprev
;
pprev
=
&
tmp
->
vm_next
;
if
(
retval
)
goto
fail_nomem
;
}
flush_tlb_mm
(
current
->
mm
);
return
0
;
fail_nomem:
exit_mmap
(
mm
);
flush_tlb_mm
(
current
->
mm
);
return
retval
;
}
static
inline
int
copy_mm
(
unsigned
long
clone_flags
,
struct
task_struct
*
tsk
)
{
if
(
!
(
clone_flags
&
CLONE_VM
))
{
struct
mm_struct
*
mm
=
kmem_cache_alloc
(
mm_cachep
,
SLAB_KERNEL
);
if
(
!
mm
)
return
-
1
;
*
mm
=
*
current
->
mm
;
init_new_context
(
mm
);
mm
->
count
=
1
;
mm
->
def_flags
=
0
;
mm
->
mmap_sem
=
MUTEX
;
/* It has not run yet, so cannot be present in anyone's
* cache or tlb.
*/
mm
->
cpu_vm_mask
=
0
;
tsk
->
mm
=
mm
;
tsk
->
min_flt
=
tsk
->
maj_flt
=
0
;
tsk
->
cmin_flt
=
tsk
->
cmaj_flt
=
0
;
tsk
->
nswap
=
tsk
->
cnswap
=
0
;
if
(
new_page_tables
(
tsk
))
goto
free_mm
;
if
(
dup_mmap
(
mm
))
{
free_page_tables
(
mm
);
free_mm:
kmem_cache_free
(
mm_cachep
,
mm
);
return
-
1
;
}
struct
mm_struct
*
mm
;
int
retval
;
if
(
clone_flags
&
CLONE_VM
)
{
current
->
mm
->
count
++
;
SET_PAGE_DIR
(
tsk
,
current
->
mm
->
pgd
);
return
0
;
}
current
->
mm
->
count
++
;
SET_PAGE_DIR
(
tsk
,
current
->
mm
->
pgd
);
retval
=
-
ENOMEM
;
mm
=
kmem_cache_alloc
(
mm_cachep
,
SLAB_KERNEL
);
if
(
!
mm
)
goto
fail_nomem
;
*
mm
=
*
current
->
mm
;
init_new_context
(
mm
);
mm
->
count
=
1
;
mm
->
def_flags
=
0
;
mm
->
mmap_sem
=
MUTEX
;
/* It has not run yet, so cannot be present in anyone's
* cache or tlb.
*/
mm
->
cpu_vm_mask
=
0
;
tsk
->
mm
=
mm
;
tsk
->
min_flt
=
tsk
->
maj_flt
=
0
;
tsk
->
cmin_flt
=
tsk
->
cmaj_flt
=
0
;
tsk
->
nswap
=
tsk
->
cnswap
=
0
;
retval
=
new_page_tables
(
tsk
);
if
(
retval
)
goto
free_mm
;
retval
=
dup_mmap
(
mm
);
if
(
retval
)
goto
free_pt
;
return
0
;
free_pt:
free_page_tables
(
mm
);
free_mm:
tsk
->
mm
=
NULL
;
kmem_cache_free
(
mm_cachep
,
mm
);
fail_nomem:
return
retval
;
}
static
inline
int
copy_fs
(
unsigned
long
clone_flags
,
struct
task_struct
*
tsk
)
...
...
@@ -478,9 +496,9 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs)
bad_fork_cleanup_sighand:
exit_sighand
(
p
);
bad_fork_cleanup_fs:
exit_fs
(
p
);
exit_fs
(
p
);
/* blocking */
bad_fork_cleanup_files:
exit_files
(
p
);
exit_files
(
p
);
/* blocking */
bad_fork_cleanup:
charge_uid
(
current
,
-
1
);
if
(
p
->
exec_domain
&&
p
->
exec_domain
->
module
)
...
...
mm/memory.c
View file @
a6d938f4
...
...
@@ -291,19 +291,20 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
return
error
;
}
static
inline
void
free_pte
(
pte_t
page
)
/*
* Return indicates whether a page was freed so caller can adjust rss
*/
static
inline
int
free_pte
(
pte_t
page
)
{
if
(
pte_present
(
page
))
{
unsigned
long
addr
=
pte_page
(
page
);
if
(
MAP_NR
(
addr
)
>=
max_mapnr
||
PageReserved
(
mem_map
+
MAP_NR
(
addr
)))
return
;
return
0
;
free_page
(
addr
);
if
(
current
->
mm
->
rss
<=
0
)
return
;
current
->
mm
->
rss
--
;
return
;
return
1
;
}
swap_free
(
pte_val
(
page
));
return
0
;
}
static
inline
void
forget_pte
(
pte_t
page
)
...
...
@@ -314,22 +315,24 @@ static inline void forget_pte(pte_t page)
}
}
static
inline
void
zap_pte_range
(
pmd_t
*
pmd
,
unsigned
long
address
,
unsigned
long
size
)
static
inline
int
zap_pte_range
(
pmd_t
*
pmd
,
unsigned
long
address
,
unsigned
long
size
)
{
pte_t
*
pte
;
int
freed
;
if
(
pmd_none
(
*
pmd
))
return
;
return
0
;
if
(
pmd_bad
(
*
pmd
))
{
printk
(
"zap_pte_range: bad pmd (%08lx)
\n
"
,
pmd_val
(
*
pmd
));
pmd_clear
(
pmd
);
return
;
return
0
;
}
pte
=
pte_offset
(
pmd
,
address
);
address
&=
~
PMD_MASK
;
if
(
address
+
size
>
PMD_SIZE
)
size
=
PMD_SIZE
-
address
;
size
>>=
PAGE_SHIFT
;
freed
=
0
;
for
(;;)
{
pte_t
page
;
if
(
!
size
)
...
...
@@ -340,32 +343,36 @@ static inline void zap_pte_range(pmd_t * pmd, unsigned long address, unsigned lo
if
(
pte_none
(
page
))
continue
;
pte_clear
(
pte
-
1
);
free_pte
(
page
);
free
d
+=
free
_pte
(
page
);
}
return
freed
;
}
static
inline
void
zap_pmd_range
(
pgd_t
*
dir
,
unsigned
long
address
,
unsigned
long
size
)
static
inline
int
zap_pmd_range
(
pgd_t
*
dir
,
unsigned
long
address
,
unsigned
long
size
)
{
pmd_t
*
pmd
;
unsigned
long
end
;
int
freed
;
if
(
pgd_none
(
*
dir
))
return
;
return
0
;
if
(
pgd_bad
(
*
dir
))
{
printk
(
"zap_pmd_range: bad pgd (%08lx)
\n
"
,
pgd_val
(
*
dir
));
pgd_clear
(
dir
);
return
;
return
0
;
}
pmd
=
pmd_offset
(
dir
,
address
);
address
&=
~
PGDIR_MASK
;
end
=
address
+
size
;
if
(
end
>
PGDIR_SIZE
)
end
=
PGDIR_SIZE
;
freed
=
0
;
do
{
zap_pte_range
(
pmd
,
address
,
end
-
address
);
freed
+=
zap_pte_range
(
pmd
,
address
,
end
-
address
);
address
=
(
address
+
PMD_SIZE
)
&
PMD_MASK
;
pmd
++
;
}
while
(
address
<
end
);
return
freed
;
}
/*
...
...
@@ -375,13 +382,22 @@ void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long s
{
pgd_t
*
dir
;
unsigned
long
end
=
address
+
size
;
int
freed
=
0
;
dir
=
pgd_offset
(
mm
,
address
);
while
(
address
<
end
)
{
zap_pmd_range
(
dir
,
address
,
end
-
address
);
freed
+=
zap_pmd_range
(
dir
,
address
,
end
-
address
);
address
=
(
address
+
PGDIR_SIZE
)
&
PGDIR_MASK
;
dir
++
;
}
/*
* Update rss for the mm_struct (not necessarily current->mm)
*/
if
(
mm
->
rss
>
0
)
{
mm
->
rss
-=
freed
;
if
(
mm
->
rss
<
0
)
mm
->
rss
=
0
;
}
}
static
inline
void
zeromap_pte_range
(
pte_t
*
pte
,
unsigned
long
address
,
unsigned
long
size
,
pte_t
zero_pte
)
...
...
mm/mmap.c
View file @
a6d938f4
...
...
@@ -373,10 +373,12 @@ unsigned long get_unmapped_area(unsigned long addr, unsigned long len)
* Unmapping between to intermediate points, making a hole.
*
* Case 4 involves the creation of 2 new areas, for each side of
* the hole.
* the hole. If possible, we reuse the existing area rather than
* allocate a new one, and the return indicates whether the old
* area was reused.
*/
static
void
unmap_fixup
(
struct
vm_area_struct
*
area
,
unsigned
long
addr
,
size_t
len
)
static
int
unmap_fixup
(
struct
vm_area_struct
*
area
,
unsigned
long
addr
,
size_t
len
,
struct
vm_area_struct
**
extra
)
{
struct
vm_area_struct
*
mpnt
;
unsigned
long
end
=
addr
+
len
;
...
...
@@ -391,7 +393,7 @@ static void unmap_fixup(struct vm_area_struct *area,
area
->
vm_ops
->
close
(
area
);
if
(
area
->
vm_dentry
)
dput
(
area
->
vm_dentry
);
return
;
return
0
;
}
/* Work out to one of the ends. */
...
...
@@ -403,17 +405,16 @@ static void unmap_fixup(struct vm_area_struct *area,
}
else
{
/* Unmapping a hole: area->vm_start < addr <= end < area->vm_end */
/* Add end mapping -- leave beginning for below */
mpnt
=
kmem_cache_alloc
(
vm_area_cachep
,
SLAB_KERNEL
);
mpnt
=
*
extra
;
*
extra
=
NULL
;
if
(
!
mpnt
)
return
;
mpnt
->
vm_mm
=
area
->
vm_mm
;
mpnt
->
vm_start
=
end
;
mpnt
->
vm_end
=
area
->
vm_end
;
mpnt
->
vm_page_prot
=
area
->
vm_page_prot
;
mpnt
->
vm_flags
=
area
->
vm_flags
;
mpnt
->
vm_ops
=
area
->
vm_ops
;
mpnt
->
vm_offset
+=
(
end
-
area
->
vm_start
);
mpnt
->
vm_offset
=
area
->
vm_offset
+
(
end
-
area
->
vm_start
);
mpnt
->
vm_dentry
=
dget
(
area
->
vm_dentry
);
if
(
mpnt
->
vm_ops
&&
mpnt
->
vm_ops
->
open
)
mpnt
->
vm_ops
->
open
(
mpnt
);
...
...
@@ -421,18 +422,18 @@ static void unmap_fixup(struct vm_area_struct *area,
insert_vm_struct
(
current
->
mm
,
mpnt
);
}
/* Construct whatever mapping is needed. */
mpnt
=
kmem_cache_alloc
(
vm_area_cachep
,
SLAB_KERNEL
);
if
(
!
mpnt
)
return
;
*
mpnt
=
*
area
;
if
(
mpnt
->
vm_ops
&&
mpnt
->
vm_ops
->
open
)
mpnt
->
vm_ops
->
open
(
mpnt
);
/* Close the current area ... */
if
(
area
->
vm_ops
&&
area
->
vm_ops
->
close
)
{
end
=
area
->
vm_end
;
/* save new end */
area
->
vm_end
=
area
->
vm_start
;
area
->
vm_ops
->
close
(
area
);
area
->
vm_end
=
end
;
}
insert_vm_struct
(
current
->
mm
,
mpnt
);
/* ... then reopen and reinsert. */
if
(
area
->
vm_ops
&&
area
->
vm_ops
->
open
)
area
->
vm_ops
->
open
(
area
);
insert_vm_struct
(
current
->
mm
,
area
);
return
1
;
}
asmlinkage
int
sys_munmap
(
unsigned
long
addr
,
size_t
len
)
...
...
@@ -452,7 +453,8 @@ asmlinkage int sys_munmap(unsigned long addr, size_t len)
*/
int
do_munmap
(
unsigned
long
addr
,
size_t
len
)
{
struct
vm_area_struct
*
mpnt
,
*
next
,
*
free
;
struct
vm_area_struct
*
mpnt
,
*
next
,
*
free
,
*
extra
;
int
freed
;
if
((
addr
&
~
PAGE_MASK
)
||
addr
>
TASK_SIZE
||
len
>
TASK_SIZE
-
addr
)
return
-
EINVAL
;
...
...
@@ -471,6 +473,14 @@ int do_munmap(unsigned long addr, size_t len)
if
(
!
mpnt
)
return
0
;
/*
* We may need one additional vma to fix up the mappings ...
* and this is the last chance for an easy error exit.
*/
extra
=
kmem_cache_alloc
(
vm_area_cachep
,
SLAB_KERNEL
);
if
(
!
extra
)
return
-
ENOMEM
;
next
=
mpnt
->
vm_next
;
/* we have mpnt->vm_next = next and addr < mpnt->vm_end */
...
...
@@ -486,19 +496,18 @@ int do_munmap(unsigned long addr, size_t len)
free
=
mpnt
;
mpnt
=
next
;
}
if
(
free
==
NULL
)
return
0
;
/* Ok - we have the memory areas we should free on the 'free' list,
* so release them, and unmap the page range..
* If the one of the segments is only being partially unmapped,
* it will put new vm_area_struct(s) into the address space.
*/
do
{
freed
=
0
;
while
((
mpnt
=
free
)
!=
NULL
)
{
unsigned
long
st
,
end
,
size
;
mpnt
=
free
;
free
=
free
->
vm_next
;
freed
=
1
;
remove_shared_vm_struct
(
mpnt
);
...
...
@@ -514,12 +523,19 @@ int do_munmap(unsigned long addr, size_t len)
zap_page_range
(
current
->
mm
,
st
,
size
);
flush_tlb_range
(
current
->
mm
,
st
,
end
);
unmap_fixup
(
mpnt
,
st
,
size
);
/*
* Fix the mapping, and free the old area if it wasn't reused.
*/
if
(
!
unmap_fixup
(
mpnt
,
st
,
size
,
&
extra
))
kmem_cache_free
(
vm_area_cachep
,
mpnt
);
}
kmem_cache_free
(
vm_area_cachep
,
mpnt
);
}
while
(
free
);
/* Release the extra vma struct if it wasn't used */
if
(
extra
)
kmem_cache_free
(
vm_area_cachep
,
extra
);
current
->
mm
->
mmap_cache
=
NULL
;
/* Kill the cache. */
if
(
freed
)
current
->
mm
->
mmap_cache
=
NULL
;
/* Kill the cache. */
return
0
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment