]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/ext4/inline.c
ext4: add normal write support for inline data
[karo-tx-linux.git] / fs / ext4 / inline.c
1 /*
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"
17 #include "truncate.h"
18
19 #define EXT4_XATTR_SYSTEM_DATA  "data"
20 #define EXT4_MIN_INLINE_DATA_SIZE       ((sizeof(__le32) * EXT4_N_BLOCKS))
21
22 int 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
30 static 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
83 out:
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  */
92 int 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
120 int 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  */
131 int 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         }
160 out:
161         brelse(is.iloc.bh);
162         return error;
163 }
164
165 static 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
201 out:
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  */
211 void 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
247 static 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
305 out:
306         brelse(is.iloc.bh);
307         return error;
308 }
309
310 static 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
367 out:
368         kfree(value);
369         brelse(is.iloc.bh);
370         return error;
371 }
372
373 int 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
398 static 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);
451 out:
452         brelse(is.iloc.bh);
453         if (error == -ENODATA)
454                 error = 0;
455         return error;
456 }
457
458 static 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
488 out:
489         return ret;
490 }
491
492 int 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
519 static 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
545 retry:
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);
617 out:
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  */
636 int 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;
701 out_up_read:
702         up_read(&EXT4_I(inode)->xattr_sem);
703 out:
704         if (handle)
705                 ext4_journal_stop(handle);
706         brelse(iloc.bh);
707         return ret;
708 convert:
709         return ext4_convert_inline_data_to_extent(mapping,
710                                                   inode, flags);
711 }
712
713 int 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);
746 out:
747         return copied;
748 }
749
750
751 int 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 }