Blame view
mm/filemap_xip.c
11.3 KB
ceffc0785 [PATCH] xip: fs/m... |
1 2 3 4 5 6 7 8 9 10 11 12 |
/* * linux/mm/filemap_xip.c * * Copyright (C) 2005 IBM Corporation * Author: Carsten Otte <cotte@de.ibm.com> * * derived from linux/mm/filemap.c - Copyright (C) Linus Torvalds * */ #include <linux/fs.h> #include <linux/pagemap.h> |
b95f1b31b mm: Map most file... |
13 |
#include <linux/export.h> |
ceffc0785 [PATCH] xip: fs/m... |
14 15 |
#include <linux/uio.h> #include <linux/rmap.h> |
cddb8a5c1 mmu-notifiers: core |
16 |
#include <linux/mmu_notifier.h> |
e8edc6e03 Detach sched.h fr... |
17 |
#include <linux/sched.h> |
538f8ea6c mm: xip fix fault... |
18 19 |
#include <linux/seqlock.h> #include <linux/mutex.h> |
5a0e3ad6a include cleanup: ... |
20 |
#include <linux/gfp.h> |
ceffc0785 [PATCH] xip: fs/m... |
21 |
#include <asm/tlbflush.h> |
70688e4dd xip: support non-... |
22 |
#include <asm/io.h> |
ceffc0785 [PATCH] xip: fs/m... |
23 24 |
/* |
a76c0b976 [PATCH] mm: fix x... |
25 26 27 |
* We do use our own empty page to avoid interference with other users * of ZERO_PAGE(), such as /dev/zero */ |
538f8ea6c mm: xip fix fault... |
28 |
static DEFINE_MUTEX(xip_sparse_mutex); |
1ca7d67cf seqcount: Add loc... |
29 |
static seqcount_t xip_sparse_seq = SEQCNT_ZERO(xip_sparse_seq); |
a76c0b976 [PATCH] mm: fix x... |
30 |
static struct page *__xip_sparse_page; |
538f8ea6c mm: xip fix fault... |
31 |
/* called under xip_sparse_mutex */ |
a76c0b976 [PATCH] mm: fix x... |
32 33 34 |
static struct page *xip_sparse_page(void) { if (!__xip_sparse_page) { |
c51b1a160 xip: fix get_zero... |
35 |
struct page *page = alloc_page(GFP_HIGHUSER | __GFP_ZERO); |
538f8ea6c mm: xip fix fault... |
36 37 |
if (page) __xip_sparse_page = page; |
a76c0b976 [PATCH] mm: fix x... |
38 39 40 41 42 |
} return __xip_sparse_page; } /* |
ceffc0785 [PATCH] xip: fs/m... |
43 |
* This is a file read routine for execute in place files, and uses |
70688e4dd xip: support non-... |
44 |
* the mapping->a_ops->get_xip_mem() function for the actual low-level |
ceffc0785 [PATCH] xip: fs/m... |
45 46 47 48 |
* stuff. * * Note the struct file* is not used at all. It may be NULL. */ |
70688e4dd xip: support non-... |
49 |
static ssize_t |
ceffc0785 [PATCH] xip: fs/m... |
50 51 52 |
do_xip_mapping_read(struct address_space *mapping, struct file_ra_state *_ra, struct file *filp, |
70688e4dd xip: support non-... |
53 54 55 |
char __user *buf, size_t len, loff_t *ppos) |
ceffc0785 [PATCH] xip: fs/m... |
56 57 |
{ struct inode *inode = mapping->host; |
2004dc8ee Use pgoff_t inste... |
58 59 |
pgoff_t index, end_index; unsigned long offset; |
70688e4dd xip: support non-... |
60 61 |
loff_t isize, pos; size_t copied = 0, error = 0; |
ceffc0785 [PATCH] xip: fs/m... |
62 |
|
70688e4dd xip: support non-... |
63 |
BUG_ON(!mapping->a_ops->get_xip_mem); |
ceffc0785 [PATCH] xip: fs/m... |
64 |
|
70688e4dd xip: support non-... |
65 66 67 |
pos = *ppos; index = pos >> PAGE_CACHE_SHIFT; offset = pos & ~PAGE_CACHE_MASK; |
ceffc0785 [PATCH] xip: fs/m... |
68 69 70 71 72 73 |
isize = i_size_read(inode); if (!isize) goto out; end_index = (isize - 1) >> PAGE_CACHE_SHIFT; |
70688e4dd xip: support non-... |
74 75 76 77 78 |
do { unsigned long nr, left; void *xip_mem; unsigned long xip_pfn; int zero = 0; |
ceffc0785 [PATCH] xip: fs/m... |
79 80 81 82 83 84 85 86 87 88 89 90 |
/* nr is the maximum number of bytes to copy from this page */ nr = PAGE_CACHE_SIZE; if (index >= end_index) { if (index > end_index) goto out; nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1; if (nr <= offset) { goto out; } } nr = nr - offset; |
58984ce21 mm: do_xip_mappin... |
91 92 |
if (nr > len - copied) nr = len - copied; |
ceffc0785 [PATCH] xip: fs/m... |
93 |
|
70688e4dd xip: support non-... |
94 95 96 97 |
error = mapping->a_ops->get_xip_mem(mapping, index, 0, &xip_mem, &xip_pfn); if (unlikely(error)) { if (error == -ENODATA) { |
ceffc0785 [PATCH] xip: fs/m... |
98 |
/* sparse */ |
70688e4dd xip: support non-... |
99 100 |
zero = 1; } else |
ceffc0785 [PATCH] xip: fs/m... |
101 |
goto out; |
afa597ba2 [PATCH] execute-i... |
102 |
} |
ceffc0785 [PATCH] xip: fs/m... |
103 104 105 106 107 108 |
/* If users can be writing to this page using arbitrary * virtual addresses, take care about potential aliasing * before reading the page on the kernel side. */ if (mapping_writably_mapped(mapping)) |
70688e4dd xip: support non-... |
109 |
/* address based flush */ ; |
ceffc0785 [PATCH] xip: fs/m... |
110 111 |
/* |
70688e4dd xip: support non-... |
112 |
* Ok, we have the mem, so now we can copy it to user space... |
ceffc0785 [PATCH] xip: fs/m... |
113 114 115 116 117 118 119 |
* * The actor routine returns how many bytes were actually used.. * NOTE! This may not be the same as how much of a user buffer * we filled up (we may be padding etc), so we can only update * "pos" here (the actor routine has to update the user buffer * pointers and the remaining count). */ |
70688e4dd xip: support non-... |
120 121 122 123 |
if (!zero) left = __copy_to_user(buf+copied, xip_mem+offset, nr); else left = __clear_user(buf + copied, nr); |
ceffc0785 [PATCH] xip: fs/m... |
124 |
|
70688e4dd xip: support non-... |
125 126 127 128 |
if (left) { error = -EFAULT; goto out; } |
ceffc0785 [PATCH] xip: fs/m... |
129 |
|
70688e4dd xip: support non-... |
130 131 132 133 134 |
copied += (nr - left); offset += (nr - left); index += offset >> PAGE_CACHE_SHIFT; offset &= ~PAGE_CACHE_MASK; } while (copied < len); |
ceffc0785 [PATCH] xip: fs/m... |
135 136 |
out: |
70688e4dd xip: support non-... |
137 |
*ppos = pos + copied; |
ceffc0785 [PATCH] xip: fs/m... |
138 139 |
if (filp) file_accessed(filp); |
70688e4dd xip: support non-... |
140 141 |
return (copied ? copied : error); |
ceffc0785 [PATCH] xip: fs/m... |
142 |
} |
ceffc0785 [PATCH] xip: fs/m... |
143 |
ssize_t |
eb6fe0c38 [PATCH] xip: redu... |
144 |
xip_file_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos) |
ceffc0785 [PATCH] xip: fs/m... |
145 |
{ |
eb6fe0c38 [PATCH] xip: redu... |
146 147 |
if (!access_ok(VERIFY_WRITE, buf, len)) return -EFAULT; |
ceffc0785 [PATCH] xip: fs/m... |
148 |
|
70688e4dd xip: support non-... |
149 150 |
return do_xip_mapping_read(filp->f_mapping, &filp->f_ra, filp, buf, len, ppos); |
ceffc0785 [PATCH] xip: fs/m... |
151 |
} |
eb6fe0c38 [PATCH] xip: redu... |
152 |
EXPORT_SYMBOL_GPL(xip_file_read); |
ceffc0785 [PATCH] xip: fs/m... |
153 |
|
ceffc0785 [PATCH] xip: fs/m... |
154 155 156 157 158 |
/* * __xip_unmap is invoked from xip_unmap and * xip_write * * This function walks all vmas of the address_space and unmaps the |
a76c0b976 [PATCH] mm: fix x... |
159 |
* __xip_sparse_page when found at pgoff. |
ceffc0785 [PATCH] xip: fs/m... |
160 161 162 163 164 165 166 |
*/ static void __xip_unmap (struct address_space * mapping, unsigned long pgoff) { struct vm_area_struct *vma; struct mm_struct *mm; |
ceffc0785 [PATCH] xip: fs/m... |
167 168 169 |
unsigned long address; pte_t *pte; pte_t pteval; |
c0718806c [PATCH] mm: rmap ... |
170 |
spinlock_t *ptl; |
67b02f119 [PATCH] mm: xip_u... |
171 |
struct page *page; |
538f8ea6c mm: xip fix fault... |
172 173 174 175 |
unsigned count; int locked = 0; count = read_seqcount_begin(&xip_sparse_seq); |
ceffc0785 [PATCH] xip: fs/m... |
176 |
|
a76c0b976 [PATCH] mm: fix x... |
177 178 179 |
page = __xip_sparse_page; if (!page) return; |
538f8ea6c mm: xip fix fault... |
180 |
retry: |
3d48ae45e mm: Convert i_mma... |
181 |
mutex_lock(&mapping->i_mmap_mutex); |
6b2dbba8b mm: replace vma p... |
182 |
vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) { |
ceffc0785 [PATCH] xip: fs/m... |
183 184 185 186 |
mm = vma->vm_mm; address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); BUG_ON(address < vma->vm_start || address >= vma->vm_end); |
479db0bf4 mm: dirty page tr... |
187 |
pte = page_check_address(page, mm, address, &ptl, 1); |
c0718806c [PATCH] mm: rmap ... |
188 |
if (pte) { |
ceffc0785 [PATCH] xip: fs/m... |
189 |
/* Nuke the page table entry. */ |
082ff0a99 [PATCH] mm/filema... |
190 |
flush_cache_page(vma, address, pte_pfn(*pte)); |
2ec74c3ef mm: move all mmu ... |
191 |
pteval = ptep_clear_flush(vma, address, pte); |
edc315fd2 badpage: remove v... |
192 |
page_remove_rmap(page); |
d559db086 mm: clean up mm_c... |
193 |
dec_mm_counter(mm, MM_FILEPAGES); |
ceffc0785 [PATCH] xip: fs/m... |
194 |
BUG_ON(pte_dirty(pteval)); |
c0718806c [PATCH] mm: rmap ... |
195 |
pte_unmap_unlock(pte, ptl); |
2ec74c3ef mm: move all mmu ... |
196 197 |
/* must invalidate_page _before_ freeing the page */ mmu_notifier_invalidate_page(mm, address); |
b5810039a [PATCH] core remo... |
198 |
page_cache_release(page); |
ceffc0785 [PATCH] xip: fs/m... |
199 200 |
} } |
3d48ae45e mm: Convert i_mma... |
201 |
mutex_unlock(&mapping->i_mmap_mutex); |
538f8ea6c mm: xip fix fault... |
202 203 204 205 206 207 208 209 |
if (locked) { mutex_unlock(&xip_sparse_mutex); } else if (read_seqcount_retry(&xip_sparse_seq, count)) { mutex_lock(&xip_sparse_mutex); locked = 1; goto retry; } |
ceffc0785 [PATCH] xip: fs/m... |
210 211 212 |
} /* |
54cb8821d mm: merge populat... |
213 |
* xip_fault() is invoked via the vma operations vector for a |
ceffc0785 [PATCH] xip: fs/m... |
214 215 |
* mapped memory region to read in file data during a page fault. * |
54cb8821d mm: merge populat... |
216 |
* This function is derived from filemap_fault, but used for execute in place |
ceffc0785 [PATCH] xip: fs/m... |
217 |
*/ |
70688e4dd xip: support non-... |
218 |
static int xip_file_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
ceffc0785 [PATCH] xip: fs/m... |
219 |
{ |
70688e4dd xip: support non-... |
220 |
struct file *file = vma->vm_file; |
ceffc0785 [PATCH] xip: fs/m... |
221 222 |
struct address_space *mapping = file->f_mapping; struct inode *inode = mapping->host; |
54cb8821d mm: merge populat... |
223 |
pgoff_t size; |
70688e4dd xip: support non-... |
224 225 226 227 |
void *xip_mem; unsigned long xip_pfn; struct page *page; int error; |
ceffc0785 [PATCH] xip: fs/m... |
228 |
|
54cb8821d mm: merge populat... |
229 |
/* XXX: are VM_FAULT_ codes OK? */ |
538f8ea6c mm: xip fix fault... |
230 |
again: |
ceffc0785 [PATCH] xip: fs/m... |
231 |
size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
d0217ac04 mm: fault feedbac... |
232 233 |
if (vmf->pgoff >= size) return VM_FAULT_SIGBUS; |
ceffc0785 [PATCH] xip: fs/m... |
234 |
|
70688e4dd xip: support non-... |
235 236 237 238 239 |
error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 0, &xip_mem, &xip_pfn); if (likely(!error)) goto found; if (error != -ENODATA) |
d0217ac04 mm: fault feedbac... |
240 |
return VM_FAULT_OOM; |
ceffc0785 [PATCH] xip: fs/m... |
241 242 |
/* sparse block */ |
70688e4dd xip: support non-... |
243 244 |
if ((vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) && (vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) && |
ceffc0785 [PATCH] xip: fs/m... |
245 |
(!(mapping->host->i_sb->s_flags & MS_RDONLY))) { |
70688e4dd xip: support non-... |
246 |
int err; |
ceffc0785 [PATCH] xip: fs/m... |
247 |
/* maybe shared writable, allocate new block */ |
14bac5acf mm: xip/ext2 fix ... |
248 |
mutex_lock(&xip_sparse_mutex); |
70688e4dd xip: support non-... |
249 250 |
error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 1, &xip_mem, &xip_pfn); |
14bac5acf mm: xip/ext2 fix ... |
251 |
mutex_unlock(&xip_sparse_mutex); |
70688e4dd xip: support non-... |
252 |
if (error) |
d0217ac04 mm: fault feedbac... |
253 |
return VM_FAULT_SIGBUS; |
70688e4dd xip: support non-... |
254 |
/* unmap sparse mappings at pgoff from all other vmas */ |
d0217ac04 mm: fault feedbac... |
255 |
__xip_unmap(mapping, vmf->pgoff); |
70688e4dd xip: support non-... |
256 257 258 259 260 261 |
found: err = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, xip_pfn); if (err == -ENOMEM) return VM_FAULT_OOM; |
99f02ef1f mm/filemap_xip.c:... |
262 263 264 265 266 267 |
/* * err == -EBUSY is fine, we've raced against another thread * that faulted-in the same page */ if (err != -EBUSY) BUG_ON(err); |
70688e4dd xip: support non-... |
268 |
return VM_FAULT_NOPAGE; |
ceffc0785 [PATCH] xip: fs/m... |
269 |
} else { |
538f8ea6c mm: xip fix fault... |
270 271 272 273 274 275 276 277 278 279 280 281 282 |
int err, ret = VM_FAULT_OOM; mutex_lock(&xip_sparse_mutex); write_seqcount_begin(&xip_sparse_seq); error = mapping->a_ops->get_xip_mem(mapping, vmf->pgoff, 0, &xip_mem, &xip_pfn); if (unlikely(!error)) { write_seqcount_end(&xip_sparse_seq); mutex_unlock(&xip_sparse_mutex); goto again; } if (error != -ENODATA) goto out; |
a76c0b976 [PATCH] mm: fix x... |
283 284 |
/* not shared and writable, use xip_sparse_page() */ page = xip_sparse_page(); |
d0217ac04 mm: fault feedbac... |
285 |
if (!page) |
538f8ea6c mm: xip fix fault... |
286 287 288 289 290 291 292 293 294 295 |
goto out; err = vm_insert_page(vma, (unsigned long)vmf->virtual_address, page); if (err == -ENOMEM) goto out; ret = VM_FAULT_NOPAGE; out: write_seqcount_end(&xip_sparse_seq); mutex_unlock(&xip_sparse_mutex); |
ceffc0785 [PATCH] xip: fs/m... |
296 |
|
538f8ea6c mm: xip fix fault... |
297 |
return ret; |
70688e4dd xip: support non-... |
298 |
} |
ceffc0785 [PATCH] xip: fs/m... |
299 |
} |
f0f37e2f7 const: mark struc... |
300 |
static const struct vm_operations_struct xip_file_vm_ops = { |
54cb8821d mm: merge populat... |
301 |
.fault = xip_file_fault, |
4fcf1c620 mm: Make default ... |
302 |
.page_mkwrite = filemap_page_mkwrite, |
0b173bc4d mm: kill vma flag... |
303 |
.remap_pages = generic_file_remap_pages, |
ceffc0785 [PATCH] xip: fs/m... |
304 305 306 307 |
}; int xip_file_mmap(struct file * file, struct vm_area_struct * vma) { |
70688e4dd xip: support non-... |
308 |
BUG_ON(!file->f_mapping->a_ops->get_xip_mem); |
ceffc0785 [PATCH] xip: fs/m... |
309 310 311 |
file_accessed(file); vma->vm_ops = &xip_file_vm_ops; |
0b173bc4d mm: kill vma flag... |
312 |
vma->vm_flags |= VM_MIXEDMAP; |
ceffc0785 [PATCH] xip: fs/m... |
313 314 315 316 317 |
return 0; } EXPORT_SYMBOL_GPL(xip_file_mmap); static ssize_t |
eb6fe0c38 [PATCH] xip: redu... |
318 319 |
__xip_file_write(struct file *filp, const char __user *buf, size_t count, loff_t pos, loff_t *ppos) |
ceffc0785 [PATCH] xip: fs/m... |
320 |
{ |
eb6fe0c38 [PATCH] xip: redu... |
321 |
struct address_space * mapping = filp->f_mapping; |
f5e54d6e5 [PATCH] mark addr... |
322 |
const struct address_space_operations *a_ops = mapping->a_ops; |
ceffc0785 [PATCH] xip: fs/m... |
323 324 |
struct inode *inode = mapping->host; long status = 0; |
ceffc0785 [PATCH] xip: fs/m... |
325 |
size_t bytes; |
ceffc0785 [PATCH] xip: fs/m... |
326 |
ssize_t written = 0; |
70688e4dd xip: support non-... |
327 |
BUG_ON(!mapping->a_ops->get_xip_mem); |
ceffc0785 [PATCH] xip: fs/m... |
328 |
|
ceffc0785 [PATCH] xip: fs/m... |
329 330 331 332 |
do { unsigned long index; unsigned long offset; size_t copied; |
70688e4dd xip: support non-... |
333 334 |
void *xip_mem; unsigned long xip_pfn; |
ceffc0785 [PATCH] xip: fs/m... |
335 336 337 338 339 340 |
offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */ index = pos >> PAGE_CACHE_SHIFT; bytes = PAGE_CACHE_SIZE - offset; if (bytes > count) bytes = count; |
70688e4dd xip: support non-... |
341 342 343 |
status = a_ops->get_xip_mem(mapping, index, 0, &xip_mem, &xip_pfn); if (status == -ENODATA) { |
ceffc0785 [PATCH] xip: fs/m... |
344 |
/* we allocate a new page unmap it */ |
14bac5acf mm: xip/ext2 fix ... |
345 |
mutex_lock(&xip_sparse_mutex); |
70688e4dd xip: support non-... |
346 347 |
status = a_ops->get_xip_mem(mapping, index, 1, &xip_mem, &xip_pfn); |
14bac5acf mm: xip/ext2 fix ... |
348 |
mutex_unlock(&xip_sparse_mutex); |
70688e4dd xip: support non-... |
349 |
if (!status) |
eb6fe0c38 [PATCH] xip: redu... |
350 351 |
/* unmap page at pgoff from all other vmas */ __xip_unmap(mapping, index); |
ceffc0785 [PATCH] xip: fs/m... |
352 |
} |
70688e4dd xip: support non-... |
353 |
if (status) |
ceffc0785 [PATCH] xip: fs/m... |
354 |
break; |
ceffc0785 [PATCH] xip: fs/m... |
355 |
|
4a9e5ef1f mm: write iovec c... |
356 |
copied = bytes - |
70688e4dd xip: support non-... |
357 |
__copy_from_user_nocache(xip_mem + offset, buf, bytes); |
4a9e5ef1f mm: write iovec c... |
358 |
|
ceffc0785 [PATCH] xip: fs/m... |
359 360 361 362 363 364 365 366 |
if (likely(copied > 0)) { status = copied; if (status >= 0) { written += status; count -= status; pos += status; buf += status; |
ceffc0785 [PATCH] xip: fs/m... |
367 368 369 370 371 372 373 374 375 376 377 |
} } if (unlikely(copied != bytes)) if (status >= 0) status = -EFAULT; if (status < 0) break; } while (count); *ppos = pos; /* * No need to use i_size_read() here, the i_size |
1b1dcc1b5 [PATCH] mutex sub... |
378 |
* cannot change under us because we hold i_mutex. |
ceffc0785 [PATCH] xip: fs/m... |
379 380 381 382 383 384 385 386 |
*/ if (pos > inode->i_size) { i_size_write(inode, pos); mark_inode_dirty(inode); } return written ? written : status; } |
eb6fe0c38 [PATCH] xip: redu... |
387 388 389 |
ssize_t xip_file_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) |
ceffc0785 [PATCH] xip: fs/m... |
390 |
{ |
eb6fe0c38 [PATCH] xip: redu... |
391 392 393 394 395 |
struct address_space *mapping = filp->f_mapping; struct inode *inode = mapping->host; size_t count; loff_t pos; ssize_t ret; |
ceffc0785 [PATCH] xip: fs/m... |
396 |
|
1b1dcc1b5 [PATCH] mutex sub... |
397 |
mutex_lock(&inode->i_mutex); |
ceffc0785 [PATCH] xip: fs/m... |
398 |
|
eb6fe0c38 [PATCH] xip: redu... |
399 400 401 |
if (!access_ok(VERIFY_READ, buf, len)) { ret=-EFAULT; goto out_up; |
ceffc0785 [PATCH] xip: fs/m... |
402 |
} |
ceffc0785 [PATCH] xip: fs/m... |
403 |
pos = *ppos; |
eb6fe0c38 [PATCH] xip: redu... |
404 |
count = len; |
ceffc0785 [PATCH] xip: fs/m... |
405 |
|
eb6fe0c38 [PATCH] xip: redu... |
406 407 |
/* We can write back this queue in page reclaim */ current->backing_dev_info = mapping->backing_dev_info; |
ceffc0785 [PATCH] xip: fs/m... |
408 |
|
eb6fe0c38 [PATCH] xip: redu... |
409 410 411 |
ret = generic_write_checks(filp, &pos, &count, S_ISBLK(inode->i_mode)); if (ret) goto out_backing; |
ceffc0785 [PATCH] xip: fs/m... |
412 |
if (count == 0) |
eb6fe0c38 [PATCH] xip: redu... |
413 |
goto out_backing; |
ceffc0785 [PATCH] xip: fs/m... |
414 |
|
2f1936b87 [patch 3/5] vfs: ... |
415 |
ret = file_remove_suid(filp); |
eb6fe0c38 [PATCH] xip: redu... |
416 417 |
if (ret) goto out_backing; |
ceffc0785 [PATCH] xip: fs/m... |
418 |
|
c3b2da314 fs: introduce ino... |
419 420 421 |
ret = file_update_time(filp); if (ret) goto out_backing; |
ceffc0785 [PATCH] xip: fs/m... |
422 |
|
eb6fe0c38 [PATCH] xip: redu... |
423 |
ret = __xip_file_write (filp, buf, count, pos, ppos); |
ceffc0785 [PATCH] xip: fs/m... |
424 |
|
eb6fe0c38 [PATCH] xip: redu... |
425 426 427 |
out_backing: current->backing_dev_info = NULL; out_up: |
1b1dcc1b5 [PATCH] mutex sub... |
428 |
mutex_unlock(&inode->i_mutex); |
ceffc0785 [PATCH] xip: fs/m... |
429 430 |
return ret; } |
eb6fe0c38 [PATCH] xip: redu... |
431 |
EXPORT_SYMBOL_GPL(xip_file_write); |
ceffc0785 [PATCH] xip: fs/m... |
432 433 434 |
/* * truncate a page used for execute in place |
70688e4dd xip: support non-... |
435 |
* functionality is analog to block_truncate_page but does use get_xip_mem |
ceffc0785 [PATCH] xip: fs/m... |
436 437 438 439 440 441 442 443 444 |
* to get the page instead of page cache */ int xip_truncate_page(struct address_space *mapping, loff_t from) { pgoff_t index = from >> PAGE_CACHE_SHIFT; unsigned offset = from & (PAGE_CACHE_SIZE-1); unsigned blocksize; unsigned length; |
70688e4dd xip: support non-... |
445 446 447 |
void *xip_mem; unsigned long xip_pfn; int err; |
ceffc0785 [PATCH] xip: fs/m... |
448 |
|
70688e4dd xip: support non-... |
449 |
BUG_ON(!mapping->a_ops->get_xip_mem); |
ceffc0785 [PATCH] xip: fs/m... |
450 451 452 453 454 455 456 457 458 |
blocksize = 1 << mapping->host->i_blkbits; length = offset & (blocksize - 1); /* Block boundary? Nothing to do */ if (!length) return 0; length = blocksize - length; |
70688e4dd xip: support non-... |
459 460 461 462 |
err = mapping->a_ops->get_xip_mem(mapping, index, 0, &xip_mem, &xip_pfn); if (unlikely(err)) { if (err == -ENODATA) |
ceffc0785 [PATCH] xip: fs/m... |
463 464 |
/* Hole? No need to truncate */ return 0; |
eb6fe0c38 [PATCH] xip: redu... |
465 |
else |
70688e4dd xip: support non-... |
466 |
return err; |
afa597ba2 [PATCH] execute-i... |
467 |
} |
70688e4dd xip: support non-... |
468 |
memset(xip_mem + offset, 0, length); |
eb6fe0c38 [PATCH] xip: redu... |
469 |
return 0; |
ceffc0785 [PATCH] xip: fs/m... |
470 471 |
} EXPORT_SYMBOL_GPL(xip_truncate_page); |