~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/libxfs/xfs_inode_fork.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Copyright (c) 2000-2006 Silicon Graphics, Inc.
  4  * All Rights Reserved.
  5  */
  6 
  7 #include "xfs.h"
  8 #include "xfs_fs.h"
  9 #include "xfs_shared.h"
 10 #include "xfs_format.h"
 11 #include "xfs_log_format.h"
 12 #include "xfs_trans_resv.h"
 13 #include "xfs_mount.h"
 14 #include "xfs_inode.h"
 15 #include "xfs_trans.h"
 16 #include "xfs_inode_item.h"
 17 #include "xfs_btree.h"
 18 #include "xfs_bmap_btree.h"
 19 #include "xfs_bmap.h"
 20 #include "xfs_error.h"
 21 #include "xfs_trace.h"
 22 #include "xfs_da_format.h"
 23 #include "xfs_da_btree.h"
 24 #include "xfs_dir2_priv.h"
 25 #include "xfs_attr_leaf.h"
 26 #include "xfs_types.h"
 27 #include "xfs_errortag.h"
 28 #include "xfs_health.h"
 29 #include "xfs_symlink_remote.h"
 30 
 31 struct kmem_cache *xfs_ifork_cache;
 32 
 33 void
 34 xfs_init_local_fork(
 35         struct xfs_inode        *ip,
 36         int                     whichfork,
 37         const void              *data,
 38         int64_t                 size)
 39 {
 40         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
 41         int                     mem_size = size;
 42         bool                    zero_terminate;
 43 
 44         /*
 45          * If we are using the local fork to store a symlink body we need to
 46          * zero-terminate it so that we can pass it back to the VFS directly.
 47          * Overallocate the in-memory fork by one for that and add a zero
 48          * to terminate it below.
 49          */
 50         zero_terminate = S_ISLNK(VFS_I(ip)->i_mode);
 51         if (zero_terminate)
 52                 mem_size++;
 53 
 54         if (size) {
 55                 char *new_data = kmalloc(mem_size,
 56                                 GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL);
 57 
 58                 memcpy(new_data, data, size);
 59                 if (zero_terminate)
 60                         new_data[size] = '\0';
 61 
 62                 ifp->if_data = new_data;
 63         } else {
 64                 ifp->if_data = NULL;
 65         }
 66 
 67         ifp->if_bytes = size;
 68 }
 69 
 70 /*
 71  * The file is in-lined in the on-disk inode.
 72  */
 73 STATIC int
 74 xfs_iformat_local(
 75         struct xfs_inode        *ip,
 76         struct xfs_dinode       *dip,
 77         int                     whichfork,
 78         int                     size)
 79 {
 80         /*
 81          * If the size is unreasonable, then something
 82          * is wrong and we just bail out rather than crash in
 83          * kmalloc() or memcpy() below.
 84          */
 85         if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
 86                 xfs_warn(ip->i_mount,
 87         "corrupt inode %llu (bad size %d for local fork, size = %zd).",
 88                         (unsigned long long) ip->i_ino, size,
 89                         XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
 90                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
 91                                 "xfs_iformat_local", dip, sizeof(*dip),
 92                                 __this_address);
 93                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
 94                 return -EFSCORRUPTED;
 95         }
 96 
 97         xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
 98         return 0;
 99 }
100 
101 /*
102  * The file consists of a set of extents all of which fit into the on-disk
103  * inode.
104  */
105 STATIC int
106 xfs_iformat_extents(
107         struct xfs_inode        *ip,
108         struct xfs_dinode       *dip,
109         int                     whichfork)
110 {
111         struct xfs_mount        *mp = ip->i_mount;
112         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
113         int                     state = xfs_bmap_fork_to_state(whichfork);
114         xfs_extnum_t            nex = xfs_dfork_nextents(dip, whichfork);
115         int                     size = nex * sizeof(xfs_bmbt_rec_t);
116         struct xfs_iext_cursor  icur;
117         struct xfs_bmbt_rec     *dp;
118         struct xfs_bmbt_irec    new;
119         int                     i;
120 
121         /*
122          * If the number of extents is unreasonable, then something is wrong and
123          * we just bail out rather than crash in kmalloc() or memcpy() below.
124          */
125         if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) {
126                 xfs_warn(ip->i_mount, "corrupt inode %llu ((a)extents = %llu).",
127                         ip->i_ino, nex);
128                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
129                                 "xfs_iformat_extents(1)", dip, sizeof(*dip),
130                                 __this_address);
131                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
132                 return -EFSCORRUPTED;
133         }
134 
135         ifp->if_bytes = 0;
136         ifp->if_data = NULL;
137         ifp->if_height = 0;
138         if (size) {
139                 dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
140 
141                 xfs_iext_first(ifp, &icur);
142                 for (i = 0; i < nex; i++, dp++) {
143                         xfs_failaddr_t  fa;
144 
145                         xfs_bmbt_disk_get_all(dp, &new);
146                         fa = xfs_bmap_validate_extent(ip, whichfork, &new);
147                         if (fa) {
148                                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
149                                                 "xfs_iformat_extents(2)",
150                                                 dp, sizeof(*dp), fa);
151                                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
152                                 return xfs_bmap_complain_bad_rec(ip, whichfork,
153                                                 fa, &new);
154                         }
155 
156                         xfs_iext_insert(ip, &icur, &new, state);
157                         trace_xfs_read_extent(ip, &icur, state, _THIS_IP_);
158                         xfs_iext_next(ifp, &icur);
159                 }
160         }
161         return 0;
162 }
163 
164 /*
165  * The file has too many extents to fit into
166  * the inode, so they are in B-tree format.
167  * Allocate a buffer for the root of the B-tree
168  * and copy the root into it.  The i_extents
169  * field will remain NULL until all of the
170  * extents are read in (when they are needed).
171  */
172 STATIC int
173 xfs_iformat_btree(
174         struct xfs_inode        *ip,
175         struct xfs_dinode       *dip,
176         int                     whichfork)
177 {
178         struct xfs_mount        *mp = ip->i_mount;
179         xfs_bmdr_block_t        *dfp;
180         struct xfs_ifork        *ifp;
181         /* REFERENCED */
182         int                     nrecs;
183         int                     size;
184         int                     level;
185 
186         ifp = xfs_ifork_ptr(ip, whichfork);
187         dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
188         size = XFS_BMAP_BROOT_SPACE(mp, dfp);
189         nrecs = be16_to_cpu(dfp->bb_numrecs);
190         level = be16_to_cpu(dfp->bb_level);
191 
192         /*
193          * blow out if -- fork has less extents than can fit in
194          * fork (fork shouldn't be a btree format), root btree
195          * block has more records than can fit into the fork,
196          * or the number of extents is greater than the number of
197          * blocks.
198          */
199         if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) ||
200                      nrecs == 0 ||
201                      XFS_BMDR_SPACE_CALC(nrecs) >
202                                         XFS_DFORK_SIZE(dip, mp, whichfork) ||
203                      ifp->if_nextents > ip->i_nblocks) ||
204                      level == 0 || level > XFS_BM_MAXLEVELS(mp, whichfork)) {
205                 xfs_warn(mp, "corrupt inode %llu (btree).",
206                                         (unsigned long long) ip->i_ino);
207                 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
208                                 "xfs_iformat_btree", dfp, size,
209                                 __this_address);
210                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
211                 return -EFSCORRUPTED;
212         }
213 
214         ifp->if_broot_bytes = size;
215         ifp->if_broot = kmalloc(size,
216                                 GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL);
217         ASSERT(ifp->if_broot != NULL);
218         /*
219          * Copy and convert from the on-disk structure
220          * to the in-memory structure.
221          */
222         xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
223                          ifp->if_broot, size);
224 
225         ifp->if_bytes = 0;
226         ifp->if_data = NULL;
227         ifp->if_height = 0;
228         return 0;
229 }
230 
231 int
232 xfs_iformat_data_fork(
233         struct xfs_inode        *ip,
234         struct xfs_dinode       *dip)
235 {
236         struct inode            *inode = VFS_I(ip);
237         int                     error;
238 
239         /*
240          * Initialize the extent count early, as the per-format routines may
241          * depend on it.  Use release semantics to set needextents /after/ we
242          * set the format. This ensures that we can use acquire semantics on
243          * needextents in xfs_need_iread_extents() and be guaranteed to see a
244          * valid format value after that load.
245          */
246         ip->i_df.if_format = dip->di_format;
247         ip->i_df.if_nextents = xfs_dfork_data_extents(dip);
248         smp_store_release(&ip->i_df.if_needextents,
249                            ip->i_df.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
250 
251         switch (inode->i_mode & S_IFMT) {
252         case S_IFIFO:
253         case S_IFCHR:
254         case S_IFBLK:
255         case S_IFSOCK:
256                 ip->i_disk_size = 0;
257                 inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip));
258                 return 0;
259         case S_IFREG:
260         case S_IFLNK:
261         case S_IFDIR:
262                 switch (ip->i_df.if_format) {
263                 case XFS_DINODE_FMT_LOCAL:
264                         error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
265                                         be64_to_cpu(dip->di_size));
266                         if (!error)
267                                 error = xfs_ifork_verify_local_data(ip);
268                         return error;
269                 case XFS_DINODE_FMT_EXTENTS:
270                         return xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
271                 case XFS_DINODE_FMT_BTREE:
272                         return xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
273                 default:
274                         xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__,
275                                         dip, sizeof(*dip), __this_address);
276                         xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
277                         return -EFSCORRUPTED;
278                 }
279                 break;
280         default:
281                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
282                                 sizeof(*dip), __this_address);
283                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
284                 return -EFSCORRUPTED;
285         }
286 }
287 
288 static uint16_t
289 xfs_dfork_attr_shortform_size(
290         struct xfs_dinode               *dip)
291 {
292         struct xfs_attr_sf_hdr          *sf = XFS_DFORK_APTR(dip);
293 
294         return be16_to_cpu(sf->totsize);
295 }
296 
297 void
298 xfs_ifork_init_attr(
299         struct xfs_inode        *ip,
300         enum xfs_dinode_fmt     format,
301         xfs_extnum_t            nextents)
302 {
303         /*
304          * Initialize the extent count early, as the per-format routines may
305          * depend on it.  Use release semantics to set needextents /after/ we
306          * set the format. This ensures that we can use acquire semantics on
307          * needextents in xfs_need_iread_extents() and be guaranteed to see a
308          * valid format value after that load.
309          */
310         ip->i_af.if_format = format;
311         ip->i_af.if_nextents = nextents;
312         smp_store_release(&ip->i_af.if_needextents,
313                            ip->i_af.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
314 }
315 
316 void
317 xfs_ifork_zap_attr(
318         struct xfs_inode        *ip)
319 {
320         xfs_idestroy_fork(&ip->i_af);
321         memset(&ip->i_af, 0, sizeof(struct xfs_ifork));
322         ip->i_af.if_format = XFS_DINODE_FMT_EXTENTS;
323 }
324 
325 int
326 xfs_iformat_attr_fork(
327         struct xfs_inode        *ip,
328         struct xfs_dinode       *dip)
329 {
330         xfs_extnum_t            naextents = xfs_dfork_attr_extents(dip);
331         int                     error = 0;
332 
333         /*
334          * Initialize the extent count early, as the per-format routines may
335          * depend on it.
336          */
337         xfs_ifork_init_attr(ip, dip->di_aformat, naextents);
338 
339         switch (ip->i_af.if_format) {
340         case XFS_DINODE_FMT_LOCAL:
341                 error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
342                                 xfs_dfork_attr_shortform_size(dip));
343                 if (!error)
344                         error = xfs_ifork_verify_local_attr(ip);
345                 break;
346         case XFS_DINODE_FMT_EXTENTS:
347                 error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
348                 break;
349         case XFS_DINODE_FMT_BTREE:
350                 error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
351                 break;
352         default:
353                 xfs_inode_verifier_error(ip, error, __func__, dip,
354                                 sizeof(*dip), __this_address);
355                 xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
356                 error = -EFSCORRUPTED;
357                 break;
358         }
359 
360         if (error)
361                 xfs_ifork_zap_attr(ip);
362         return error;
363 }
364 
365 /*
366  * Reallocate the space for if_broot based on the number of records
367  * being added or deleted as indicated in rec_diff.  Move the records
368  * and pointers in if_broot to fit the new size.  When shrinking this
369  * will eliminate holes between the records and pointers created by
370  * the caller.  When growing this will create holes to be filled in
371  * by the caller.
372  *
373  * The caller must not request to add more records than would fit in
374  * the on-disk inode root.  If the if_broot is currently NULL, then
375  * if we are adding records, one will be allocated.  The caller must also
376  * not request that the number of records go below zero, although
377  * it can go to zero.
378  *
379  * ip -- the inode whose if_broot area is changing
380  * ext_diff -- the change in the number of records, positive or negative,
381  *       requested for the if_broot array.
382  */
383 void
384 xfs_iroot_realloc(
385         xfs_inode_t             *ip,
386         int                     rec_diff,
387         int                     whichfork)
388 {
389         struct xfs_mount        *mp = ip->i_mount;
390         int                     cur_max;
391         struct xfs_ifork        *ifp;
392         struct xfs_btree_block  *new_broot;
393         int                     new_max;
394         size_t                  new_size;
395         char                    *np;
396         char                    *op;
397 
398         /*
399          * Handle the degenerate case quietly.
400          */
401         if (rec_diff == 0) {
402                 return;
403         }
404 
405         ifp = xfs_ifork_ptr(ip, whichfork);
406         if (rec_diff > 0) {
407                 /*
408                  * If there wasn't any memory allocated before, just
409                  * allocate it now and get out.
410                  */
411                 if (ifp->if_broot_bytes == 0) {
412                         new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
413                         ifp->if_broot = kmalloc(new_size,
414                                                 GFP_KERNEL | __GFP_NOFAIL);
415                         ifp->if_broot_bytes = (int)new_size;
416                         return;
417                 }
418 
419                 /*
420                  * If there is already an existing if_broot, then we need
421                  * to realloc() it and shift the pointers to their new
422                  * location.  The records don't change location because
423                  * they are kept butted up against the btree block header.
424                  */
425                 cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
426                 new_max = cur_max + rec_diff;
427                 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
428                 ifp->if_broot = krealloc(ifp->if_broot, new_size,
429                                          GFP_KERNEL | __GFP_NOFAIL);
430                 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
431                                                      ifp->if_broot_bytes);
432                 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
433                                                      (int)new_size);
434                 ifp->if_broot_bytes = (int)new_size;
435                 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
436                         xfs_inode_fork_size(ip, whichfork));
437                 memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t));
438                 return;
439         }
440 
441         /*
442          * rec_diff is less than 0.  In this case, we are shrinking the
443          * if_broot buffer.  It must already exist.  If we go to zero
444          * records, just get rid of the root and clear the status bit.
445          */
446         ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
447         cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
448         new_max = cur_max + rec_diff;
449         ASSERT(new_max >= 0);
450         if (new_max > 0)
451                 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
452         else
453                 new_size = 0;
454         if (new_size > 0) {
455                 new_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL);
456                 /*
457                  * First copy over the btree block header.
458                  */
459                 memcpy(new_broot, ifp->if_broot,
460                         XFS_BMBT_BLOCK_LEN(ip->i_mount));
461         } else {
462                 new_broot = NULL;
463         }
464 
465         /*
466          * Only copy the records and pointers if there are any.
467          */
468         if (new_max > 0) {
469                 /*
470                  * First copy the records.
471                  */
472                 op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1);
473                 np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1);
474                 memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t));
475 
476                 /*
477                  * Then copy the pointers.
478                  */
479                 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
480                                                      ifp->if_broot_bytes);
481                 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1,
482                                                      (int)new_size);
483                 memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
484         }
485         kfree(ifp->if_broot);
486         ifp->if_broot = new_broot;
487         ifp->if_broot_bytes = (int)new_size;
488         if (ifp->if_broot)
489                 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
490                         xfs_inode_fork_size(ip, whichfork));
491         return;
492 }
493 
494 
495 /*
496  * This is called when the amount of space needed for if_data
497  * is increased or decreased.  The change in size is indicated by
498  * the number of bytes that need to be added or deleted in the
499  * byte_diff parameter.
500  *
501  * If the amount of space needed has decreased below the size of the
502  * inline buffer, then switch to using the inline buffer.  Otherwise,
503  * use krealloc() or kmalloc() to adjust the size of the buffer
504  * to what is needed.
505  *
506  * ip -- the inode whose if_data area is changing
507  * byte_diff -- the change in the number of bytes, positive or negative,
508  *       requested for the if_data array.
509  */
510 void *
511 xfs_idata_realloc(
512         struct xfs_inode        *ip,
513         int64_t                 byte_diff,
514         int                     whichfork)
515 {
516         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
517         int64_t                 new_size = ifp->if_bytes + byte_diff;
518 
519         ASSERT(new_size >= 0);
520         ASSERT(new_size <= xfs_inode_fork_size(ip, whichfork));
521 
522         if (byte_diff) {
523                 ifp->if_data = krealloc(ifp->if_data, new_size,
524                                         GFP_KERNEL | __GFP_NOFAIL);
525                 if (new_size == 0)
526                         ifp->if_data = NULL;
527                 ifp->if_bytes = new_size;
528         }
529 
530         return ifp->if_data;
531 }
532 
533 /* Free all memory and reset a fork back to its initial state. */
534 void
535 xfs_idestroy_fork(
536         struct xfs_ifork        *ifp)
537 {
538         if (ifp->if_broot != NULL) {
539                 kfree(ifp->if_broot);
540                 ifp->if_broot = NULL;
541         }
542 
543         switch (ifp->if_format) {
544         case XFS_DINODE_FMT_LOCAL:
545                 kfree(ifp->if_data);
546                 ifp->if_data = NULL;
547                 break;
548         case XFS_DINODE_FMT_EXTENTS:
549         case XFS_DINODE_FMT_BTREE:
550                 if (ifp->if_height)
551                         xfs_iext_destroy(ifp);
552                 break;
553         }
554 }
555 
556 /*
557  * Convert in-core extents to on-disk form
558  *
559  * In the case of the data fork, the in-core and on-disk fork sizes can be
560  * different due to delayed allocation extents. We only copy on-disk extents
561  * here, so callers must always use the physical fork size to determine the
562  * size of the buffer passed to this routine.  We will return the size actually
563  * used.
564  */
565 int
566 xfs_iextents_copy(
567         struct xfs_inode        *ip,
568         struct xfs_bmbt_rec     *dp,
569         int                     whichfork)
570 {
571         int                     state = xfs_bmap_fork_to_state(whichfork);
572         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
573         struct xfs_iext_cursor  icur;
574         struct xfs_bmbt_irec    rec;
575         int64_t                 copied = 0;
576 
577         xfs_assert_ilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED);
578         ASSERT(ifp->if_bytes > 0);
579 
580         for_each_xfs_iext(ifp, &icur, &rec) {
581                 if (isnullstartblock(rec.br_startblock))
582                         continue;
583                 ASSERT(xfs_bmap_validate_extent(ip, whichfork, &rec) == NULL);
584                 xfs_bmbt_disk_set_all(dp, &rec);
585                 trace_xfs_write_extent(ip, &icur, state, _RET_IP_);
586                 copied += sizeof(struct xfs_bmbt_rec);
587                 dp++;
588         }
589 
590         ASSERT(copied > 0);
591         ASSERT(copied <= ifp->if_bytes);
592         return copied;
593 }
594 
595 /*
596  * Each of the following cases stores data into the same region
597  * of the on-disk inode, so only one of them can be valid at
598  * any given time. While it is possible to have conflicting formats
599  * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is
600  * in EXTENTS format, this can only happen when the fork has
601  * changed formats after being modified but before being flushed.
602  * In these cases, the format always takes precedence, because the
603  * format indicates the current state of the fork.
604  */
605 void
606 xfs_iflush_fork(
607         struct xfs_inode        *ip,
608         struct xfs_dinode       *dip,
609         struct xfs_inode_log_item *iip,
610         int                     whichfork)
611 {
612         char                    *cp;
613         struct xfs_ifork        *ifp;
614         xfs_mount_t             *mp;
615         static const short      brootflag[2] =
616                 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
617         static const short      dataflag[2] =
618                 { XFS_ILOG_DDATA, XFS_ILOG_ADATA };
619         static const short      extflag[2] =
620                 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
621 
622         if (!iip)
623                 return;
624         ifp = xfs_ifork_ptr(ip, whichfork);
625         /*
626          * This can happen if we gave up in iformat in an error path,
627          * for the attribute fork.
628          */
629         if (!ifp) {
630                 ASSERT(whichfork == XFS_ATTR_FORK);
631                 return;
632         }
633         cp = XFS_DFORK_PTR(dip, whichfork);
634         mp = ip->i_mount;
635         switch (ifp->if_format) {
636         case XFS_DINODE_FMT_LOCAL:
637                 if ((iip->ili_fields & dataflag[whichfork]) &&
638                     (ifp->if_bytes > 0)) {
639                         ASSERT(ifp->if_data != NULL);
640                         ASSERT(ifp->if_bytes <= xfs_inode_fork_size(ip, whichfork));
641                         memcpy(cp, ifp->if_data, ifp->if_bytes);
642                 }
643                 break;
644 
645         case XFS_DINODE_FMT_EXTENTS:
646                 if ((iip->ili_fields & extflag[whichfork]) &&
647                     (ifp->if_bytes > 0)) {
648                         ASSERT(ifp->if_nextents > 0);
649                         (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
650                                 whichfork);
651                 }
652                 break;
653 
654         case XFS_DINODE_FMT_BTREE:
655                 if ((iip->ili_fields & brootflag[whichfork]) &&
656                     (ifp->if_broot_bytes > 0)) {
657                         ASSERT(ifp->if_broot != NULL);
658                         ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
659                                 xfs_inode_fork_size(ip, whichfork));
660                         xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
661                                 (xfs_bmdr_block_t *)cp,
662                                 XFS_DFORK_SIZE(dip, mp, whichfork));
663                 }
664                 break;
665 
666         case XFS_DINODE_FMT_DEV:
667                 if (iip->ili_fields & XFS_ILOG_DEV) {
668                         ASSERT(whichfork == XFS_DATA_FORK);
669                         xfs_dinode_put_rdev(dip,
670                                         linux_to_xfs_dev_t(VFS_I(ip)->i_rdev));
671                 }
672                 break;
673 
674         default:
675                 ASSERT(0);
676                 break;
677         }
678 }
679 
680 /* Convert bmap state flags to an inode fork. */
681 struct xfs_ifork *
682 xfs_iext_state_to_fork(
683         struct xfs_inode        *ip,
684         int                     state)
685 {
686         if (state & BMAP_COWFORK)
687                 return ip->i_cowfp;
688         else if (state & BMAP_ATTRFORK)
689                 return &ip->i_af;
690         return &ip->i_df;
691 }
692 
693 /*
694  * Initialize an inode's copy-on-write fork.
695  */
696 void
697 xfs_ifork_init_cow(
698         struct xfs_inode        *ip)
699 {
700         if (ip->i_cowfp)
701                 return;
702 
703         ip->i_cowfp = kmem_cache_zalloc(xfs_ifork_cache,
704                                 GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL);
705         ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS;
706 }
707 
708 /* Verify the inline contents of the data fork of an inode. */
709 int
710 xfs_ifork_verify_local_data(
711         struct xfs_inode        *ip)
712 {
713         xfs_failaddr_t          fa = NULL;
714 
715         switch (VFS_I(ip)->i_mode & S_IFMT) {
716         case S_IFDIR: {
717                 struct xfs_mount        *mp = ip->i_mount;
718                 struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
719                 struct xfs_dir2_sf_hdr  *sfp = ifp->if_data;
720 
721                 fa = xfs_dir2_sf_verify(mp, sfp, ifp->if_bytes);
722                 break;
723         }
724         case S_IFLNK: {
725                 struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK);
726 
727                 fa = xfs_symlink_shortform_verify(ifp->if_data, ifp->if_bytes);
728                 break;
729         }
730         default:
731                 break;
732         }
733 
734         if (fa) {
735                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "data fork",
736                                 ip->i_df.if_data, ip->i_df.if_bytes, fa);
737                 return -EFSCORRUPTED;
738         }
739 
740         return 0;
741 }
742 
743 /* Verify the inline contents of the attr fork of an inode. */
744 int
745 xfs_ifork_verify_local_attr(
746         struct xfs_inode        *ip)
747 {
748         struct xfs_ifork        *ifp = &ip->i_af;
749         xfs_failaddr_t          fa;
750 
751         if (!xfs_inode_has_attr_fork(ip)) {
752                 fa = __this_address;
753         } else {
754                 struct xfs_ifork                *ifp = &ip->i_af;
755 
756                 ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL);
757                 fa = xfs_attr_shortform_verify(ifp->if_data, ifp->if_bytes);
758         }
759         if (fa) {
760                 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "attr fork",
761                                 ifp->if_data, ifp->if_bytes, fa);
762                 return -EFSCORRUPTED;
763         }
764 
765         return 0;
766 }
767 
768 /*
769  * Check if the inode fork supports adding nr_to_add more extents.
770  *
771  * If it doesn't but we can upgrade it to large extent counters, do the upgrade.
772  * If we can't upgrade or are already using big counters but still can't fit the
773  * additional extents, return -EFBIG.
774  */
775 int
776 xfs_iext_count_extend(
777         struct xfs_trans        *tp,
778         struct xfs_inode        *ip,
779         int                     whichfork,
780         uint                    nr_to_add)
781 {
782         struct xfs_mount        *mp = ip->i_mount;
783         bool                    has_large =
784                 xfs_inode_has_large_extent_counts(ip);
785         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, whichfork);
786         uint64_t                nr_exts;
787 
788         ASSERT(nr_to_add <= XFS_MAX_EXTCNT_UPGRADE_NR);
789 
790         if (whichfork == XFS_COW_FORK)
791                 return 0;
792 
793         /* no point in upgrading if if_nextents overflows */
794         nr_exts = ifp->if_nextents + nr_to_add;
795         if (nr_exts < ifp->if_nextents)
796                 return -EFBIG;
797 
798         if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_REDUCE_MAX_IEXTENTS) &&
799             nr_exts > 10)
800                 return -EFBIG;
801 
802         if (nr_exts > xfs_iext_max_nextents(has_large, whichfork)) {
803                 if (has_large || !xfs_has_large_extent_counts(mp))
804                         return -EFBIG;
805                 ip->i_diflags2 |= XFS_DIFLAG2_NREXT64;
806                 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
807         }
808         return 0;
809 }
810 
811 /* Decide if a file mapping is on the realtime device or not. */
812 bool
813 xfs_ifork_is_realtime(
814         struct xfs_inode        *ip,
815         int                     whichfork)
816 {
817         return XFS_IS_REALTIME_INODE(ip) && whichfork != XFS_ATTR_FORK;
818 }
819 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php