blob: 320ff6fe5d8c00e09490cefc3ad024c320895241 [file] [log] [blame]
Tao Ma67cf5b02012-12-10 14:04:46 -05001/*
2 * Copyright (c) 2012 Taobao.
3 * Written by Tao Ma <boyu.mt@taobao.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2.1 of the GNU Lesser General Public License
7 * as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#include "ext4_jbd2.h"
15#include "ext4.h"
16#include "xattr.h"
Tao Maf19d5872012-12-10 14:05:51 -050017#include "truncate.h"
Tao Ma67cf5b02012-12-10 14:04:46 -050018
19#define EXT4_XATTR_SYSTEM_DATA "data"
20#define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS))
21
22int ext4_get_inline_size(struct inode *inode)
23{
24 if (EXT4_I(inode)->i_inline_off)
25 return EXT4_I(inode)->i_inline_size;
26
27 return 0;
28}
29
30static int get_max_inline_xattr_value_size(struct inode *inode,
31 struct ext4_iloc *iloc)
32{
33 struct ext4_xattr_ibody_header *header;
34 struct ext4_xattr_entry *entry;
35 struct ext4_inode *raw_inode;
36 int free, min_offs;
37
38 min_offs = EXT4_SB(inode->i_sb)->s_inode_size -
39 EXT4_GOOD_OLD_INODE_SIZE -
40 EXT4_I(inode)->i_extra_isize -
41 sizeof(struct ext4_xattr_ibody_header);
42
43 /*
44 * We need to subtract another sizeof(__u32) since an in-inode xattr
45 * needs an empty 4 bytes to indicate the gap between the xattr entry
46 * and the name/value pair.
47 */
48 if (!ext4_test_inode_state(inode, EXT4_STATE_XATTR))
49 return EXT4_XATTR_SIZE(min_offs -
50 EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA)) -
51 EXT4_XATTR_ROUND - sizeof(__u32));
52
53 raw_inode = ext4_raw_inode(iloc);
54 header = IHDR(inode, raw_inode);
55 entry = IFIRST(header);
56
57 /* Compute min_offs. */
58 for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
59 if (!entry->e_value_block && entry->e_value_size) {
60 size_t offs = le16_to_cpu(entry->e_value_offs);
61 if (offs < min_offs)
62 min_offs = offs;
63 }
64 }
65 free = min_offs -
66 ((void *)entry - (void *)IFIRST(header)) - sizeof(__u32);
67
68 if (EXT4_I(inode)->i_inline_off) {
69 entry = (struct ext4_xattr_entry *)
70 ((void *)raw_inode + EXT4_I(inode)->i_inline_off);
71
72 free += le32_to_cpu(entry->e_value_size);
73 goto out;
74 }
75
76 free -= EXT4_XATTR_LEN(strlen(EXT4_XATTR_SYSTEM_DATA));
77
78 if (free > EXT4_XATTR_ROUND)
79 free = EXT4_XATTR_SIZE(free - EXT4_XATTR_ROUND);
80 else
81 free = 0;
82
83out:
84 return free;
85}
86
87/*
88 * Get the maximum size we now can store in an inode.
89 * If we can't find the space for a xattr entry, don't use the space
90 * of the extents since we have no space to indicate the inline data.
91 */
92int ext4_get_max_inline_size(struct inode *inode)
93{
94 int error, max_inline_size;
95 struct ext4_iloc iloc;
96
97 if (EXT4_I(inode)->i_extra_isize == 0)
98 return 0;
99
100 error = ext4_get_inode_loc(inode, &iloc);
101 if (error) {
102 ext4_error_inode(inode, __func__, __LINE__, 0,
103 "can't get inode location %lu",
104 inode->i_ino);
105 return 0;
106 }
107
108 down_read(&EXT4_I(inode)->xattr_sem);
109 max_inline_size = get_max_inline_xattr_value_size(inode, &iloc);
110 up_read(&EXT4_I(inode)->xattr_sem);
111
112 brelse(iloc.bh);
113
114 if (!max_inline_size)
115 return 0;
116
117 return max_inline_size + EXT4_MIN_INLINE_DATA_SIZE;
118}
119
120int ext4_has_inline_data(struct inode *inode)
121{
122 return ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA) &&
123 EXT4_I(inode)->i_inline_off;
124}
125
126/*
127 * this function does not take xattr_sem, which is OK because it is
128 * currently only used in a code path coming form ext4_iget, before
129 * the new inode has been unlocked
130 */
131int ext4_find_inline_data_nolock(struct inode *inode)
132{
133 struct ext4_xattr_ibody_find is = {
134 .s = { .not_found = -ENODATA, },
135 };
136 struct ext4_xattr_info i = {
137 .name_index = EXT4_XATTR_INDEX_SYSTEM,
138 .name = EXT4_XATTR_SYSTEM_DATA,
139 };
140 int error;
141
142 if (EXT4_I(inode)->i_extra_isize == 0)
143 return 0;
144
145 error = ext4_get_inode_loc(inode, &is.iloc);
146 if (error)
147 return error;
148
149 error = ext4_xattr_ibody_find(inode, &i, &is);
150 if (error)
151 goto out;
152
153 if (!is.s.not_found) {
154 EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
155 (void *)ext4_raw_inode(&is.iloc));
156 EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +
157 le32_to_cpu(is.s.here->e_value_size);
158 ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
159 }
160out:
161 brelse(is.iloc.bh);
162 return error;
163}
164
165static int ext4_read_inline_data(struct inode *inode, void *buffer,
166 unsigned int len,
167 struct ext4_iloc *iloc)
168{
169 struct ext4_xattr_entry *entry;
170 struct ext4_xattr_ibody_header *header;
171 int cp_len = 0;
172 struct ext4_inode *raw_inode;
173
174 if (!len)
175 return 0;
176
177 BUG_ON(len > EXT4_I(inode)->i_inline_size);
178
179 cp_len = len < EXT4_MIN_INLINE_DATA_SIZE ?
180 len : EXT4_MIN_INLINE_DATA_SIZE;
181
182 raw_inode = ext4_raw_inode(iloc);
183 memcpy(buffer, (void *)(raw_inode->i_block), cp_len);
184
185 len -= cp_len;
186 buffer += cp_len;
187
188 if (!len)
189 goto out;
190
191 header = IHDR(inode, raw_inode);
192 entry = (struct ext4_xattr_entry *)((void *)raw_inode +
193 EXT4_I(inode)->i_inline_off);
194 len = min_t(unsigned int, len,
195 (unsigned int)le32_to_cpu(entry->e_value_size));
196
197 memcpy(buffer,
198 (void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs), len);
199 cp_len += len;
200
201out:
202 return cp_len;
203}
204
205/*
206 * write the buffer to the inline inode.
207 * If 'create' is set, we don't need to do the extra copy in the xattr
208 * value since it is already handled by ext4_xattr_ibody_set. That saves
209 * us one memcpy.
210 */
211void ext4_write_inline_data(struct inode *inode, struct ext4_iloc *iloc,
212 void *buffer, loff_t pos, unsigned int len)
213{
214 struct ext4_xattr_entry *entry;
215 struct ext4_xattr_ibody_header *header;
216 struct ext4_inode *raw_inode;
217 int cp_len = 0;
218
219 BUG_ON(!EXT4_I(inode)->i_inline_off);
220 BUG_ON(pos + len > EXT4_I(inode)->i_inline_size);
221
222 raw_inode = ext4_raw_inode(iloc);
223 buffer += pos;
224
225 if (pos < EXT4_MIN_INLINE_DATA_SIZE) {
226 cp_len = pos + len > EXT4_MIN_INLINE_DATA_SIZE ?
227 EXT4_MIN_INLINE_DATA_SIZE - pos : len;
228 memcpy((void *)raw_inode->i_block + pos, buffer, cp_len);
229
230 len -= cp_len;
231 buffer += cp_len;
232 pos += cp_len;
233 }
234
235 if (!len)
236 return;
237
238 pos -= EXT4_MIN_INLINE_DATA_SIZE;
239 header = IHDR(inode, raw_inode);
240 entry = (struct ext4_xattr_entry *)((void *)raw_inode +
241 EXT4_I(inode)->i_inline_off);
242
243 memcpy((void *)IFIRST(header) + le16_to_cpu(entry->e_value_offs) + pos,
244 buffer, len);
245}
246
247static int ext4_create_inline_data(handle_t *handle,
248 struct inode *inode, unsigned len)
249{
250 int error;
251 void *value = NULL;
252 struct ext4_xattr_ibody_find is = {
253 .s = { .not_found = -ENODATA, },
254 };
255 struct ext4_xattr_info i = {
256 .name_index = EXT4_XATTR_INDEX_SYSTEM,
257 .name = EXT4_XATTR_SYSTEM_DATA,
258 };
259
260 error = ext4_get_inode_loc(inode, &is.iloc);
261 if (error)
262 return error;
263
264 error = ext4_journal_get_write_access(handle, is.iloc.bh);
265 if (error)
266 goto out;
267
268 if (len > EXT4_MIN_INLINE_DATA_SIZE) {
269 value = (void *)empty_zero_page;
270 len -= EXT4_MIN_INLINE_DATA_SIZE;
271 } else {
272 value = "";
273 len = 0;
274 }
275
276 /* Insert the the xttr entry. */
277 i.value = value;
278 i.value_len = len;
279
280 error = ext4_xattr_ibody_find(inode, &i, &is);
281 if (error)
282 goto out;
283
284 BUG_ON(!is.s.not_found);
285
286 error = ext4_xattr_ibody_set(handle, inode, &i, &is);
287 if (error) {
288 if (error == -ENOSPC)
289 ext4_clear_inode_state(inode,
290 EXT4_STATE_MAY_INLINE_DATA);
291 goto out;
292 }
293
294 memset((void *)ext4_raw_inode(&is.iloc)->i_block,
295 0, EXT4_MIN_INLINE_DATA_SIZE);
296
297 EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
298 (void *)ext4_raw_inode(&is.iloc));
299 EXT4_I(inode)->i_inline_size = len + EXT4_MIN_INLINE_DATA_SIZE;
300 ext4_clear_inode_flag(inode, EXT4_INODE_EXTENTS);
301 ext4_set_inode_flag(inode, EXT4_INODE_INLINE_DATA);
302 get_bh(is.iloc.bh);
303 error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
304
305out:
306 brelse(is.iloc.bh);
307 return error;
308}
309
310static int ext4_update_inline_data(handle_t *handle, struct inode *inode,
311 unsigned int len)
312{
313 int error;
314 void *value = NULL;
315 struct ext4_xattr_ibody_find is = {
316 .s = { .not_found = -ENODATA, },
317 };
318 struct ext4_xattr_info i = {
319 .name_index = EXT4_XATTR_INDEX_SYSTEM,
320 .name = EXT4_XATTR_SYSTEM_DATA,
321 };
322
323 /* If the old space is ok, write the data directly. */
324 if (len <= EXT4_I(inode)->i_inline_size)
325 return 0;
326
327 error = ext4_get_inode_loc(inode, &is.iloc);
328 if (error)
329 return error;
330
331 error = ext4_xattr_ibody_find(inode, &i, &is);
332 if (error)
333 goto out;
334
335 BUG_ON(is.s.not_found);
336
337 len -= EXT4_MIN_INLINE_DATA_SIZE;
338 value = kzalloc(len, GFP_NOFS);
339 if (!value)
340 goto out;
341
342 error = ext4_xattr_ibody_get(inode, i.name_index, i.name,
343 value, len);
344 if (error == -ENODATA)
345 goto out;
346
347 error = ext4_journal_get_write_access(handle, is.iloc.bh);
348 if (error)
349 goto out;
350
351 /* Update the xttr entry. */
352 i.value = value;
353 i.value_len = len;
354
355 error = ext4_xattr_ibody_set(handle, inode, &i, &is);
356 if (error)
357 goto out;
358
359 EXT4_I(inode)->i_inline_off = (u16)((void *)is.s.here -
360 (void *)ext4_raw_inode(&is.iloc));
361 EXT4_I(inode)->i_inline_size = EXT4_MIN_INLINE_DATA_SIZE +
362 le32_to_cpu(is.s.here->e_value_size);
363 ext4_set_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
364 get_bh(is.iloc.bh);
365 error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
366
367out:
368 kfree(value);
369 brelse(is.iloc.bh);
370 return error;
371}
372
373int ext4_prepare_inline_data(handle_t *handle, struct inode *inode,
374 unsigned int len)
375{
376 int ret, size;
377 struct ext4_inode_info *ei = EXT4_I(inode);
378
379 if (!ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA))
380 return -ENOSPC;
381
382 size = ext4_get_max_inline_size(inode);
383 if (size < len)
384 return -ENOSPC;
385
386 down_write(&EXT4_I(inode)->xattr_sem);
387
388 if (ei->i_inline_off)
389 ret = ext4_update_inline_data(handle, inode, len);
390 else
391 ret = ext4_create_inline_data(handle, inode, len);
392
393 up_write(&EXT4_I(inode)->xattr_sem);
394
395 return ret;
396}
397
398static int ext4_destroy_inline_data_nolock(handle_t *handle,
399 struct inode *inode)
400{
401 struct ext4_inode_info *ei = EXT4_I(inode);
402 struct ext4_xattr_ibody_find is = {
403 .s = { .not_found = 0, },
404 };
405 struct ext4_xattr_info i = {
406 .name_index = EXT4_XATTR_INDEX_SYSTEM,
407 .name = EXT4_XATTR_SYSTEM_DATA,
408 .value = NULL,
409 .value_len = 0,
410 };
411 int error;
412
413 if (!ei->i_inline_off)
414 return 0;
415
416 error = ext4_get_inode_loc(inode, &is.iloc);
417 if (error)
418 return error;
419
420 error = ext4_xattr_ibody_find(inode, &i, &is);
421 if (error)
422 goto out;
423
424 error = ext4_journal_get_write_access(handle, is.iloc.bh);
425 if (error)
426 goto out;
427
428 error = ext4_xattr_ibody_set(handle, inode, &i, &is);
429 if (error)
430 goto out;
431
432 memset((void *)ext4_raw_inode(&is.iloc)->i_block,
433 0, EXT4_MIN_INLINE_DATA_SIZE);
434
435 if (EXT4_HAS_INCOMPAT_FEATURE(inode->i_sb,
436 EXT4_FEATURE_INCOMPAT_EXTENTS)) {
437 if (S_ISDIR(inode->i_mode) ||
438 S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) {
439 ext4_set_inode_flag(inode, EXT4_INODE_EXTENTS);
440 ext4_ext_tree_init(handle, inode);
441 }
442 }
443 ext4_clear_inode_flag(inode, EXT4_INODE_INLINE_DATA);
444
445 get_bh(is.iloc.bh);
446 error = ext4_mark_iloc_dirty(handle, inode, &is.iloc);
447
448 EXT4_I(inode)->i_inline_off = 0;
449 EXT4_I(inode)->i_inline_size = 0;
450 ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
451out:
452 brelse(is.iloc.bh);
453 if (error == -ENODATA)
454 error = 0;
455 return error;
456}
457
Tao Ma46c7f252012-12-10 14:04:52 -0500458static int ext4_read_inline_page(struct inode *inode, struct page *page)
459{
460 void *kaddr;
461 int ret = 0;
462 size_t len;
463 struct ext4_iloc iloc;
464
465 BUG_ON(!PageLocked(page));
466 BUG_ON(!ext4_has_inline_data(inode));
467 BUG_ON(page->index);
468
469 if (!EXT4_I(inode)->i_inline_off) {
470 ext4_warning(inode->i_sb, "inode %lu doesn't have inline data.",
471 inode->i_ino);
472 goto out;
473 }
474
475 ret = ext4_get_inode_loc(inode, &iloc);
476 if (ret)
477 goto out;
478
479 len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode));
480 kaddr = kmap_atomic(page);
481 ret = ext4_read_inline_data(inode, kaddr, len, &iloc);
482 flush_dcache_page(page);
483 kunmap_atomic(kaddr);
484 zero_user_segment(page, len, PAGE_CACHE_SIZE);
485 SetPageUptodate(page);
486 brelse(iloc.bh);
487
488out:
489 return ret;
490}
491
492int ext4_readpage_inline(struct inode *inode, struct page *page)
493{
494 int ret = 0;
495
496 down_read(&EXT4_I(inode)->xattr_sem);
497 if (!ext4_has_inline_data(inode)) {
498 up_read(&EXT4_I(inode)->xattr_sem);
499 return -EAGAIN;
500 }
501
502 /*
503 * Current inline data can only exist in the 1st page,
504 * So for all the other pages, just set them uptodate.
505 */
506 if (!page->index)
507 ret = ext4_read_inline_page(inode, page);
508 else if (!PageUptodate(page)) {
509 zero_user_segment(page, 0, PAGE_CACHE_SIZE);
510 SetPageUptodate(page);
511 }
512
513 up_read(&EXT4_I(inode)->xattr_sem);
514
515 unlock_page(page);
516 return ret >= 0 ? 0 : ret;
517}
518
Tao Maf19d5872012-12-10 14:05:51 -0500519static int ext4_convert_inline_data_to_extent(struct address_space *mapping,
520 struct inode *inode,
521 unsigned flags)
522{
523 int ret, needed_blocks;
524 handle_t *handle = NULL;
525 int retries = 0, sem_held = 0;
526 struct page *page = NULL;
527 unsigned from, to;
528 struct ext4_iloc iloc;
529
530 if (!ext4_has_inline_data(inode)) {
531 /*
532 * clear the flag so that no new write
533 * will trap here again.
534 */
535 ext4_clear_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA);
536 return 0;
537 }
538
539 needed_blocks = ext4_writepage_trans_blocks(inode);
540
541 ret = ext4_get_inode_loc(inode, &iloc);
542 if (ret)
543 return ret;
544
545retry:
546 handle = ext4_journal_start(inode, needed_blocks);
547 if (IS_ERR(handle)) {
548 ret = PTR_ERR(handle);
549 handle = NULL;
550 goto out;
551 }
552
553 /* We cannot recurse into the filesystem as the transaction is already
554 * started */
555 flags |= AOP_FLAG_NOFS;
556
557 page = grab_cache_page_write_begin(mapping, 0, flags);
558 if (!page) {
559 ret = -ENOMEM;
560 goto out;
561 }
562
563 down_write(&EXT4_I(inode)->xattr_sem);
564 sem_held = 1;
565 /* If some one has already done this for us, just exit. */
566 if (!ext4_has_inline_data(inode)) {
567 ret = 0;
568 goto out;
569 }
570
571 from = 0;
572 to = ext4_get_inline_size(inode);
573 if (!PageUptodate(page)) {
574 ret = ext4_read_inline_page(inode, page);
575 if (ret < 0)
576 goto out;
577 }
578
579 ret = ext4_destroy_inline_data_nolock(handle, inode);
580 if (ret)
581 goto out;
582
583 if (ext4_should_dioread_nolock(inode))
584 ret = __block_write_begin(page, from, to, ext4_get_block_write);
585 else
586 ret = __block_write_begin(page, from, to, ext4_get_block);
587
588 if (!ret && ext4_should_journal_data(inode)) {
589 ret = ext4_walk_page_buffers(handle, page_buffers(page),
590 from, to, NULL,
591 do_journal_get_write_access);
592 }
593
594 if (ret) {
595 unlock_page(page);
596 page_cache_release(page);
597 ext4_orphan_add(handle, inode);
598 up_write(&EXT4_I(inode)->xattr_sem);
599 sem_held = 0;
600 ext4_journal_stop(handle);
601 handle = NULL;
602 ext4_truncate_failed_write(inode);
603 /*
604 * If truncate failed early the inode might
605 * still be on the orphan list; we need to
606 * make sure the inode is removed from the
607 * orphan list in that case.
608 */
609 if (inode->i_nlink)
610 ext4_orphan_del(NULL, inode);
611 }
612
613 if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
614 goto retry;
615
616 block_commit_write(page, from, to);
617out:
618 if (page) {
619 unlock_page(page);
620 page_cache_release(page);
621 }
622 if (sem_held)
623 up_write(&EXT4_I(inode)->xattr_sem);
624 if (handle)
625 ext4_journal_stop(handle);
626 brelse(iloc.bh);
627 return ret;
628}
629
630/*
631 * Try to write data in the inode.
632 * If the inode has inline data, check whether the new write can be
633 * in the inode also. If not, create the page the handle, move the data
634 * to the page make it update and let the later codes create extent for it.
635 */
636int ext4_try_to_write_inline_data(struct address_space *mapping,
637 struct inode *inode,
638 loff_t pos, unsigned len,
639 unsigned flags,
640 struct page **pagep)
641{
642 int ret;
643 handle_t *handle;
644 struct page *page;
645 struct ext4_iloc iloc;
646
647 if (pos + len > ext4_get_max_inline_size(inode))
648 goto convert;
649
650 ret = ext4_get_inode_loc(inode, &iloc);
651 if (ret)
652 return ret;
653
654 /*
655 * The possible write could happen in the inode,
656 * so try to reserve the space in inode first.
657 */
658 handle = ext4_journal_start(inode, 1);
659 if (IS_ERR(handle)) {
660 ret = PTR_ERR(handle);
661 handle = NULL;
662 goto out;
663 }
664
665 ret = ext4_prepare_inline_data(handle, inode, pos + len);
666 if (ret && ret != -ENOSPC)
667 goto out;
668
669 /* We don't have space in inline inode, so convert it to extent. */
670 if (ret == -ENOSPC) {
671 ext4_journal_stop(handle);
672 brelse(iloc.bh);
673 goto convert;
674 }
675
676 flags |= AOP_FLAG_NOFS;
677
678 page = grab_cache_page_write_begin(mapping, 0, flags);
679 if (!page) {
680 ret = -ENOMEM;
681 goto out;
682 }
683
684 *pagep = page;
685 down_read(&EXT4_I(inode)->xattr_sem);
686 if (!ext4_has_inline_data(inode)) {
687 ret = 0;
688 unlock_page(page);
689 page_cache_release(page);
690 goto out_up_read;
691 }
692
693 if (!PageUptodate(page)) {
694 ret = ext4_read_inline_page(inode, page);
695 if (ret < 0)
696 goto out_up_read;
697 }
698
699 ret = 1;
700 handle = NULL;
701out_up_read:
702 up_read(&EXT4_I(inode)->xattr_sem);
703out:
704 if (handle)
705 ext4_journal_stop(handle);
706 brelse(iloc.bh);
707 return ret;
708convert:
709 return ext4_convert_inline_data_to_extent(mapping,
710 inode, flags);
711}
712
713int ext4_write_inline_data_end(struct inode *inode, loff_t pos, unsigned len,
714 unsigned copied, struct page *page)
715{
716 int ret;
717 void *kaddr;
718 struct ext4_iloc iloc;
719
720 if (unlikely(copied < len)) {
721 if (!PageUptodate(page)) {
722 copied = 0;
723 goto out;
724 }
725 }
726
727 ret = ext4_get_inode_loc(inode, &iloc);
728 if (ret) {
729 ext4_std_error(inode->i_sb, ret);
730 copied = 0;
731 goto out;
732 }
733
734 down_write(&EXT4_I(inode)->xattr_sem);
735 BUG_ON(!ext4_has_inline_data(inode));
736
737 kaddr = kmap_atomic(page);
738 ext4_write_inline_data(inode, &iloc, kaddr, pos, len);
739 kunmap_atomic(kaddr);
740 SetPageUptodate(page);
741 /* clear page dirty so that writepages wouldn't work for us. */
742 ClearPageDirty(page);
743
744 up_write(&EXT4_I(inode)->xattr_sem);
745 brelse(iloc.bh);
746out:
747 return copied;
748}
749
750
Tao Ma67cf5b02012-12-10 14:04:46 -0500751int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)
752{
753 int ret;
754
755 down_write(&EXT4_I(inode)->xattr_sem);
756 ret = ext4_destroy_inline_data_nolock(handle, inode);
757 up_write(&EXT4_I(inode)->xattr_sem);
758
759 return ret;
760}