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

TOMOYO Linux Cross Reference
Linux/fs/xfs/libxfs/xfs_inode_util.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 #include <linux/iversion.h>
  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_sb.h"
 14 #include "xfs_mount.h"
 15 #include "xfs_inode.h"
 16 #include "xfs_inode_util.h"
 17 #include "xfs_trans.h"
 18 #include "xfs_ialloc.h"
 19 #include "xfs_health.h"
 20 #include "xfs_bmap.h"
 21 #include "xfs_error.h"
 22 #include "xfs_trace.h"
 23 #include "xfs_ag.h"
 24 #include "xfs_iunlink_item.h"
 25 #include "xfs_inode_item.h"
 26 
 27 uint16_t
 28 xfs_flags2diflags(
 29         struct xfs_inode        *ip,
 30         unsigned int            xflags)
 31 {
 32         /* can't set PREALLOC this way, just preserve it */
 33         uint16_t                di_flags =
 34                 (ip->i_diflags & XFS_DIFLAG_PREALLOC);
 35 
 36         if (xflags & FS_XFLAG_IMMUTABLE)
 37                 di_flags |= XFS_DIFLAG_IMMUTABLE;
 38         if (xflags & FS_XFLAG_APPEND)
 39                 di_flags |= XFS_DIFLAG_APPEND;
 40         if (xflags & FS_XFLAG_SYNC)
 41                 di_flags |= XFS_DIFLAG_SYNC;
 42         if (xflags & FS_XFLAG_NOATIME)
 43                 di_flags |= XFS_DIFLAG_NOATIME;
 44         if (xflags & FS_XFLAG_NODUMP)
 45                 di_flags |= XFS_DIFLAG_NODUMP;
 46         if (xflags & FS_XFLAG_NODEFRAG)
 47                 di_flags |= XFS_DIFLAG_NODEFRAG;
 48         if (xflags & FS_XFLAG_FILESTREAM)
 49                 di_flags |= XFS_DIFLAG_FILESTREAM;
 50         if (S_ISDIR(VFS_I(ip)->i_mode)) {
 51                 if (xflags & FS_XFLAG_RTINHERIT)
 52                         di_flags |= XFS_DIFLAG_RTINHERIT;
 53                 if (xflags & FS_XFLAG_NOSYMLINKS)
 54                         di_flags |= XFS_DIFLAG_NOSYMLINKS;
 55                 if (xflags & FS_XFLAG_EXTSZINHERIT)
 56                         di_flags |= XFS_DIFLAG_EXTSZINHERIT;
 57                 if (xflags & FS_XFLAG_PROJINHERIT)
 58                         di_flags |= XFS_DIFLAG_PROJINHERIT;
 59         } else if (S_ISREG(VFS_I(ip)->i_mode)) {
 60                 if (xflags & FS_XFLAG_REALTIME)
 61                         di_flags |= XFS_DIFLAG_REALTIME;
 62                 if (xflags & FS_XFLAG_EXTSIZE)
 63                         di_flags |= XFS_DIFLAG_EXTSIZE;
 64         }
 65 
 66         return di_flags;
 67 }
 68 
 69 uint64_t
 70 xfs_flags2diflags2(
 71         struct xfs_inode        *ip,
 72         unsigned int            xflags)
 73 {
 74         uint64_t                di_flags2 =
 75                 (ip->i_diflags2 & (XFS_DIFLAG2_REFLINK |
 76                                    XFS_DIFLAG2_BIGTIME |
 77                                    XFS_DIFLAG2_NREXT64));
 78 
 79         if (xflags & FS_XFLAG_DAX)
 80                 di_flags2 |= XFS_DIFLAG2_DAX;
 81         if (xflags & FS_XFLAG_COWEXTSIZE)
 82                 di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
 83 
 84         return di_flags2;
 85 }
 86 
 87 uint32_t
 88 xfs_ip2xflags(
 89         struct xfs_inode        *ip)
 90 {
 91         uint32_t                flags = 0;
 92 
 93         if (ip->i_diflags & XFS_DIFLAG_ANY) {
 94                 if (ip->i_diflags & XFS_DIFLAG_REALTIME)
 95                         flags |= FS_XFLAG_REALTIME;
 96                 if (ip->i_diflags & XFS_DIFLAG_PREALLOC)
 97                         flags |= FS_XFLAG_PREALLOC;
 98                 if (ip->i_diflags & XFS_DIFLAG_IMMUTABLE)
 99                         flags |= FS_XFLAG_IMMUTABLE;
100                 if (ip->i_diflags & XFS_DIFLAG_APPEND)
101                         flags |= FS_XFLAG_APPEND;
102                 if (ip->i_diflags & XFS_DIFLAG_SYNC)
103                         flags |= FS_XFLAG_SYNC;
104                 if (ip->i_diflags & XFS_DIFLAG_NOATIME)
105                         flags |= FS_XFLAG_NOATIME;
106                 if (ip->i_diflags & XFS_DIFLAG_NODUMP)
107                         flags |= FS_XFLAG_NODUMP;
108                 if (ip->i_diflags & XFS_DIFLAG_RTINHERIT)
109                         flags |= FS_XFLAG_RTINHERIT;
110                 if (ip->i_diflags & XFS_DIFLAG_PROJINHERIT)
111                         flags |= FS_XFLAG_PROJINHERIT;
112                 if (ip->i_diflags & XFS_DIFLAG_NOSYMLINKS)
113                         flags |= FS_XFLAG_NOSYMLINKS;
114                 if (ip->i_diflags & XFS_DIFLAG_EXTSIZE)
115                         flags |= FS_XFLAG_EXTSIZE;
116                 if (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT)
117                         flags |= FS_XFLAG_EXTSZINHERIT;
118                 if (ip->i_diflags & XFS_DIFLAG_NODEFRAG)
119                         flags |= FS_XFLAG_NODEFRAG;
120                 if (ip->i_diflags & XFS_DIFLAG_FILESTREAM)
121                         flags |= FS_XFLAG_FILESTREAM;
122         }
123 
124         if (ip->i_diflags2 & XFS_DIFLAG2_ANY) {
125                 if (ip->i_diflags2 & XFS_DIFLAG2_DAX)
126                         flags |= FS_XFLAG_DAX;
127                 if (ip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE)
128                         flags |= FS_XFLAG_COWEXTSIZE;
129         }
130 
131         if (xfs_inode_has_attr_fork(ip))
132                 flags |= FS_XFLAG_HASATTR;
133         return flags;
134 }
135 
136 prid_t
137 xfs_get_initial_prid(struct xfs_inode *dp)
138 {
139         if (dp->i_diflags & XFS_DIFLAG_PROJINHERIT)
140                 return dp->i_projid;
141 
142         /* Assign to the root project by default. */
143         return 0;
144 }
145 
146 /* Propagate di_flags from a parent inode to a child inode. */
147 static inline void
148 xfs_inode_inherit_flags(
149         struct xfs_inode        *ip,
150         const struct xfs_inode  *pip)
151 {
152         unsigned int            di_flags = 0;
153         xfs_failaddr_t          failaddr;
154         umode_t                 mode = VFS_I(ip)->i_mode;
155 
156         if (S_ISDIR(mode)) {
157                 if (pip->i_diflags & XFS_DIFLAG_RTINHERIT)
158                         di_flags |= XFS_DIFLAG_RTINHERIT;
159                 if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
160                         di_flags |= XFS_DIFLAG_EXTSZINHERIT;
161                         ip->i_extsize = pip->i_extsize;
162                 }
163                 if (pip->i_diflags & XFS_DIFLAG_PROJINHERIT)
164                         di_flags |= XFS_DIFLAG_PROJINHERIT;
165         } else if (S_ISREG(mode)) {
166                 if ((pip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
167                     xfs_has_realtime(ip->i_mount))
168                         di_flags |= XFS_DIFLAG_REALTIME;
169                 if (pip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) {
170                         di_flags |= XFS_DIFLAG_EXTSIZE;
171                         ip->i_extsize = pip->i_extsize;
172                 }
173         }
174         if ((pip->i_diflags & XFS_DIFLAG_NOATIME) &&
175             xfs_inherit_noatime)
176                 di_flags |= XFS_DIFLAG_NOATIME;
177         if ((pip->i_diflags & XFS_DIFLAG_NODUMP) &&
178             xfs_inherit_nodump)
179                 di_flags |= XFS_DIFLAG_NODUMP;
180         if ((pip->i_diflags & XFS_DIFLAG_SYNC) &&
181             xfs_inherit_sync)
182                 di_flags |= XFS_DIFLAG_SYNC;
183         if ((pip->i_diflags & XFS_DIFLAG_NOSYMLINKS) &&
184             xfs_inherit_nosymlinks)
185                 di_flags |= XFS_DIFLAG_NOSYMLINKS;
186         if ((pip->i_diflags & XFS_DIFLAG_NODEFRAG) &&
187             xfs_inherit_nodefrag)
188                 di_flags |= XFS_DIFLAG_NODEFRAG;
189         if (pip->i_diflags & XFS_DIFLAG_FILESTREAM)
190                 di_flags |= XFS_DIFLAG_FILESTREAM;
191 
192         ip->i_diflags |= di_flags;
193 
194         /*
195          * Inode verifiers on older kernels only check that the extent size
196          * hint is an integer multiple of the rt extent size on realtime files.
197          * They did not check the hint alignment on a directory with both
198          * rtinherit and extszinherit flags set.  If the misaligned hint is
199          * propagated from a directory into a new realtime file, new file
200          * allocations will fail due to math errors in the rt allocator and/or
201          * trip the verifiers.  Validate the hint settings in the new file so
202          * that we don't let broken hints propagate.
203          */
204         failaddr = xfs_inode_validate_extsize(ip->i_mount, ip->i_extsize,
205                         VFS_I(ip)->i_mode, ip->i_diflags);
206         if (failaddr) {
207                 ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
208                                    XFS_DIFLAG_EXTSZINHERIT);
209                 ip->i_extsize = 0;
210         }
211 }
212 
213 /* Propagate di_flags2 from a parent inode to a child inode. */
214 static inline void
215 xfs_inode_inherit_flags2(
216         struct xfs_inode        *ip,
217         const struct xfs_inode  *pip)
218 {
219         xfs_failaddr_t          failaddr;
220 
221         if (pip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) {
222                 ip->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE;
223                 ip->i_cowextsize = pip->i_cowextsize;
224         }
225         if (pip->i_diflags2 & XFS_DIFLAG2_DAX)
226                 ip->i_diflags2 |= XFS_DIFLAG2_DAX;
227 
228         /* Don't let invalid cowextsize hints propagate. */
229         failaddr = xfs_inode_validate_cowextsize(ip->i_mount, ip->i_cowextsize,
230                         VFS_I(ip)->i_mode, ip->i_diflags, ip->i_diflags2);
231         if (failaddr) {
232                 ip->i_diflags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
233                 ip->i_cowextsize = 0;
234         }
235 }
236 
237 /*
238  * If we need to create attributes immediately after allocating the inode,
239  * initialise an empty attribute fork right now. We use the default fork offset
240  * for attributes here as we don't know exactly what size or how many
241  * attributes we might be adding. We can do this safely here because we know
242  * the data fork is completely empty and this saves us from needing to run a
243  * separate transaction to set the fork offset in the immediate future.
244  *
245  * If we have parent pointers and the caller hasn't told us that the file will
246  * never be linked into a directory tree, we /must/ create the attr fork.
247  */
248 static inline bool
249 xfs_icreate_want_attrfork(
250         struct xfs_mount                *mp,
251         const struct xfs_icreate_args   *args)
252 {
253         if (args->flags & XFS_ICREATE_INIT_XATTRS)
254                 return true;
255 
256         if (!(args->flags & XFS_ICREATE_UNLINKABLE) && xfs_has_parent(mp))
257                 return true;
258 
259         return false;
260 }
261 
262 /* Initialise an inode's attributes. */
263 void
264 xfs_inode_init(
265         struct xfs_trans        *tp,
266         const struct xfs_icreate_args *args,
267         struct xfs_inode        *ip)
268 {
269         struct xfs_inode        *pip = args->pip;
270         struct inode            *dir = pip ? VFS_I(pip) : NULL;
271         struct xfs_mount        *mp = tp->t_mountp;
272         struct inode            *inode = VFS_I(ip);
273         unsigned int            flags;
274         int                     times = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG |
275                                         XFS_ICHGTIME_ACCESS;
276 
277         if (args->flags & XFS_ICREATE_TMPFILE)
278                 set_nlink(inode, 0);
279         else if (S_ISDIR(args->mode))
280                 set_nlink(inode, 2);
281         else
282                 set_nlink(inode, 1);
283         inode->i_rdev = args->rdev;
284 
285         if (!args->idmap || pip == NULL) {
286                 /* creating a tree root, sb rooted, or detached file */
287                 inode->i_uid = GLOBAL_ROOT_UID;
288                 inode->i_gid = GLOBAL_ROOT_GID;
289                 ip->i_projid = 0;
290                 inode->i_mode = args->mode;
291         } else {
292                 /* creating a child in the directory tree */
293                 if (dir && !(dir->i_mode & S_ISGID) && xfs_has_grpid(mp)) {
294                         inode_fsuid_set(inode, args->idmap);
295                         inode->i_gid = dir->i_gid;
296                         inode->i_mode = args->mode;
297                 } else {
298                         inode_init_owner(args->idmap, inode, dir, args->mode);
299                 }
300 
301                 /*
302                  * If the group ID of the new file does not match the effective
303                  * group ID or one of the supplementary group IDs, the S_ISGID
304                  * bit is cleared (and only if the irix_sgid_inherit
305                  * compatibility variable is set).
306                  */
307                 if (irix_sgid_inherit && (inode->i_mode & S_ISGID) &&
308                     !vfsgid_in_group_p(i_gid_into_vfsgid(args->idmap, inode)))
309                         inode->i_mode &= ~S_ISGID;
310 
311                 ip->i_projid = pip ? xfs_get_initial_prid(pip) : 0;
312         }
313 
314         ip->i_disk_size = 0;
315         ip->i_df.if_nextents = 0;
316         ASSERT(ip->i_nblocks == 0);
317 
318         ip->i_extsize = 0;
319         ip->i_diflags = 0;
320 
321         if (xfs_has_v3inodes(mp)) {
322                 inode_set_iversion(inode, 1);
323                 ip->i_cowextsize = 0;
324                 times |= XFS_ICHGTIME_CREATE;
325         }
326 
327         xfs_trans_ichgtime(tp, ip, times);
328 
329         flags = XFS_ILOG_CORE;
330         switch (args->mode & S_IFMT) {
331         case S_IFIFO:
332         case S_IFCHR:
333         case S_IFBLK:
334         case S_IFSOCK:
335                 ip->i_df.if_format = XFS_DINODE_FMT_DEV;
336                 flags |= XFS_ILOG_DEV;
337                 break;
338         case S_IFREG:
339         case S_IFDIR:
340                 if (pip && (pip->i_diflags & XFS_DIFLAG_ANY))
341                         xfs_inode_inherit_flags(ip, pip);
342                 if (pip && (pip->i_diflags2 & XFS_DIFLAG2_ANY))
343                         xfs_inode_inherit_flags2(ip, pip);
344                 fallthrough;
345         case S_IFLNK:
346                 ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
347                 ip->i_df.if_bytes = 0;
348                 ip->i_df.if_data = NULL;
349                 break;
350         default:
351                 ASSERT(0);
352         }
353 
354         if (xfs_icreate_want_attrfork(mp, args)) {
355                 ip->i_forkoff = xfs_default_attroffset(ip) >> 3;
356                 xfs_ifork_init_attr(ip, XFS_DINODE_FMT_EXTENTS, 0);
357 
358                 if (!xfs_has_attr(mp)) {
359                         spin_lock(&mp->m_sb_lock);
360                         xfs_add_attr(mp);
361                         spin_unlock(&mp->m_sb_lock);
362                         xfs_log_sb(tp);
363                 }
364         }
365 
366         xfs_trans_log_inode(tp, ip, flags);
367 }
368 
369 /*
370  * In-Core Unlinked List Lookups
371  * =============================
372  *
373  * Every inode is supposed to be reachable from some other piece of metadata
374  * with the exception of the root directory.  Inodes with a connection to a
375  * file descriptor but not linked from anywhere in the on-disk directory tree
376  * are collectively known as unlinked inodes, though the filesystem itself
377  * maintains links to these inodes so that on-disk metadata are consistent.
378  *
379  * XFS implements a per-AG on-disk hash table of unlinked inodes.  The AGI
380  * header contains a number of buckets that point to an inode, and each inode
381  * record has a pointer to the next inode in the hash chain.  This
382  * singly-linked list causes scaling problems in the iunlink remove function
383  * because we must walk that list to find the inode that points to the inode
384  * being removed from the unlinked hash bucket list.
385  *
386  * Hence we keep an in-memory double linked list to link each inode on an
387  * unlinked list. Because there are 64 unlinked lists per AGI, keeping pointer
388  * based lists would require having 64 list heads in the perag, one for each
389  * list. This is expensive in terms of memory (think millions of AGs) and cache
390  * misses on lookups. Instead, use the fact that inodes on the unlinked list
391  * must be referenced at the VFS level to keep them on the list and hence we
392  * have an existence guarantee for inodes on the unlinked list.
393  *
394  * Given we have an existence guarantee, we can use lockless inode cache lookups
395  * to resolve aginos to xfs inodes. This means we only need 8 bytes per inode
396  * for the double linked unlinked list, and we don't need any extra locking to
397  * keep the list safe as all manipulations are done under the AGI buffer lock.
398  * Keeping the list up to date does not require memory allocation, just finding
399  * the XFS inode and updating the next/prev unlinked list aginos.
400  */
401 
402 /*
403  * Update the prev pointer of the next agino.  Returns -ENOLINK if the inode
404  * is not in cache.
405  */
406 static int
407 xfs_iunlink_update_backref(
408         struct xfs_perag        *pag,
409         xfs_agino_t             prev_agino,
410         xfs_agino_t             next_agino)
411 {
412         struct xfs_inode        *ip;
413 
414         /* No update necessary if we are at the end of the list. */
415         if (next_agino == NULLAGINO)
416                 return 0;
417 
418         ip = xfs_iunlink_lookup(pag, next_agino);
419         if (!ip)
420                 return -ENOLINK;
421 
422         ip->i_prev_unlinked = prev_agino;
423         return 0;
424 }
425 
426 /*
427  * Point the AGI unlinked bucket at an inode and log the results.  The caller
428  * is responsible for validating the old value.
429  */
430 STATIC int
431 xfs_iunlink_update_bucket(
432         struct xfs_trans        *tp,
433         struct xfs_perag        *pag,
434         struct xfs_buf          *agibp,
435         unsigned int            bucket_index,
436         xfs_agino_t             new_agino)
437 {
438         struct xfs_agi          *agi = agibp->b_addr;
439         xfs_agino_t             old_value;
440         int                     offset;
441 
442         ASSERT(xfs_verify_agino_or_null(pag, new_agino));
443 
444         old_value = be32_to_cpu(agi->agi_unlinked[bucket_index]);
445         trace_xfs_iunlink_update_bucket(tp->t_mountp, pag->pag_agno, bucket_index,
446                         old_value, new_agino);
447 
448         /*
449          * We should never find the head of the list already set to the value
450          * passed in because either we're adding or removing ourselves from the
451          * head of the list.
452          */
453         if (old_value == new_agino) {
454                 xfs_buf_mark_corrupt(agibp);
455                 xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI);
456                 return -EFSCORRUPTED;
457         }
458 
459         agi->agi_unlinked[bucket_index] = cpu_to_be32(new_agino);
460         offset = offsetof(struct xfs_agi, agi_unlinked) +
461                         (sizeof(xfs_agino_t) * bucket_index);
462         xfs_trans_log_buf(tp, agibp, offset, offset + sizeof(xfs_agino_t) - 1);
463         return 0;
464 }
465 
466 static int
467 xfs_iunlink_insert_inode(
468         struct xfs_trans        *tp,
469         struct xfs_perag        *pag,
470         struct xfs_buf          *agibp,
471         struct xfs_inode        *ip)
472 {
473         struct xfs_mount        *mp = tp->t_mountp;
474         struct xfs_agi          *agi = agibp->b_addr;
475         xfs_agino_t             next_agino;
476         xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
477         short                   bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
478         int                     error;
479 
480         /*
481          * Get the index into the agi hash table for the list this inode will
482          * go on.  Make sure the pointer isn't garbage and that this inode
483          * isn't already on the list.
484          */
485         next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
486         if (next_agino == agino ||
487             !xfs_verify_agino_or_null(pag, next_agino)) {
488                 xfs_buf_mark_corrupt(agibp);
489                 xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI);
490                 return -EFSCORRUPTED;
491         }
492 
493         /*
494          * Update the prev pointer in the next inode to point back to this
495          * inode.
496          */
497         error = xfs_iunlink_update_backref(pag, agino, next_agino);
498         if (error == -ENOLINK)
499                 error = xfs_iunlink_reload_next(tp, agibp, agino, next_agino);
500         if (error)
501                 return error;
502 
503         if (next_agino != NULLAGINO) {
504                 /*
505                  * There is already another inode in the bucket, so point this
506                  * inode to the current head of the list.
507                  */
508                 error = xfs_iunlink_log_inode(tp, ip, pag, next_agino);
509                 if (error)
510                         return error;
511                 ip->i_next_unlinked = next_agino;
512         }
513 
514         /* Point the head of the list to point to this inode. */
515         ip->i_prev_unlinked = NULLAGINO;
516         return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino);
517 }
518 
519 /*
520  * This is called when the inode's link count has gone to 0 or we are creating
521  * a tmpfile via O_TMPFILE.  The inode @ip must have nlink == 0.
522  *
523  * We place the on-disk inode on a list in the AGI.  It will be pulled from this
524  * list when the inode is freed.
525  */
526 int
527 xfs_iunlink(
528         struct xfs_trans        *tp,
529         struct xfs_inode        *ip)
530 {
531         struct xfs_mount        *mp = tp->t_mountp;
532         struct xfs_perag        *pag;
533         struct xfs_buf          *agibp;
534         int                     error;
535 
536         ASSERT(VFS_I(ip)->i_nlink == 0);
537         ASSERT(VFS_I(ip)->i_mode != 0);
538         trace_xfs_iunlink(ip);
539 
540         pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
541 
542         /* Get the agi buffer first.  It ensures lock ordering on the list. */
543         error = xfs_read_agi(pag, tp, 0, &agibp);
544         if (error)
545                 goto out;
546 
547         error = xfs_iunlink_insert_inode(tp, pag, agibp, ip);
548 out:
549         xfs_perag_put(pag);
550         return error;
551 }
552 
553 static int
554 xfs_iunlink_remove_inode(
555         struct xfs_trans        *tp,
556         struct xfs_perag        *pag,
557         struct xfs_buf          *agibp,
558         struct xfs_inode        *ip)
559 {
560         struct xfs_mount        *mp = tp->t_mountp;
561         struct xfs_agi          *agi = agibp->b_addr;
562         xfs_agino_t             agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
563         xfs_agino_t             head_agino;
564         short                   bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
565         int                     error;
566 
567         trace_xfs_iunlink_remove(ip);
568 
569         /*
570          * Get the index into the agi hash table for the list this inode will
571          * go on.  Make sure the head pointer isn't garbage.
572          */
573         head_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
574         if (!xfs_verify_agino(pag, head_agino)) {
575                 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
576                                 agi, sizeof(*agi));
577                 xfs_ag_mark_sick(pag, XFS_SICK_AG_AGI);
578                 return -EFSCORRUPTED;
579         }
580 
581         /*
582          * Set our inode's next_unlinked pointer to NULL and then return
583          * the old pointer value so that we can update whatever was previous
584          * to us in the list to point to whatever was next in the list.
585          */
586         error = xfs_iunlink_log_inode(tp, ip, pag, NULLAGINO);
587         if (error)
588                 return error;
589 
590         /*
591          * Update the prev pointer in the next inode to point back to previous
592          * inode in the chain.
593          */
594         error = xfs_iunlink_update_backref(pag, ip->i_prev_unlinked,
595                         ip->i_next_unlinked);
596         if (error == -ENOLINK)
597                 error = xfs_iunlink_reload_next(tp, agibp, ip->i_prev_unlinked,
598                                 ip->i_next_unlinked);
599         if (error)
600                 return error;
601 
602         if (head_agino != agino) {
603                 struct xfs_inode        *prev_ip;
604 
605                 prev_ip = xfs_iunlink_lookup(pag, ip->i_prev_unlinked);
606                 if (!prev_ip) {
607                         xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE);
608                         return -EFSCORRUPTED;
609                 }
610 
611                 error = xfs_iunlink_log_inode(tp, prev_ip, pag,
612                                 ip->i_next_unlinked);
613                 prev_ip->i_next_unlinked = ip->i_next_unlinked;
614         } else {
615                 /* Point the head of the list to the next unlinked inode. */
616                 error = xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index,
617                                 ip->i_next_unlinked);
618         }
619 
620         ip->i_next_unlinked = NULLAGINO;
621         ip->i_prev_unlinked = 0;
622         return error;
623 }
624 
625 /*
626  * Pull the on-disk inode from the AGI unlinked list.
627  */
628 int
629 xfs_iunlink_remove(
630         struct xfs_trans        *tp,
631         struct xfs_perag        *pag,
632         struct xfs_inode        *ip)
633 {
634         struct xfs_buf          *agibp;
635         int                     error;
636 
637         trace_xfs_iunlink_remove(ip);
638 
639         /* Get the agi buffer first.  It ensures lock ordering on the list. */
640         error = xfs_read_agi(pag, tp, 0, &agibp);
641         if (error)
642                 return error;
643 
644         return xfs_iunlink_remove_inode(tp, pag, agibp, ip);
645 }
646 
647 /*
648  * Decrement the link count on an inode & log the change.  If this causes the
649  * link count to go to zero, move the inode to AGI unlinked list so that it can
650  * be freed when the last active reference goes away via xfs_inactive().
651  */
652 int
653 xfs_droplink(
654         struct xfs_trans        *tp,
655         struct xfs_inode        *ip)
656 {
657         struct inode            *inode = VFS_I(ip);
658 
659         xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
660 
661         if (inode->i_nlink == 0) {
662                 xfs_info_ratelimited(tp->t_mountp,
663  "Inode 0x%llx link count dropped below zero.  Pinning link count.",
664                                 ip->i_ino);
665                 set_nlink(inode, XFS_NLINK_PINNED);
666         }
667         if (inode->i_nlink != XFS_NLINK_PINNED)
668                 drop_nlink(inode);
669 
670         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
671 
672         if (inode->i_nlink)
673                 return 0;
674 
675         return xfs_iunlink(tp, ip);
676 }
677 
678 /*
679  * Increment the link count on an inode & log the change.
680  */
681 void
682 xfs_bumplink(
683         struct xfs_trans        *tp,
684         struct xfs_inode        *ip)
685 {
686         struct inode            *inode = VFS_I(ip);
687 
688         xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_CHG);
689 
690         if (inode->i_nlink == XFS_NLINK_PINNED - 1)
691                 xfs_info_ratelimited(tp->t_mountp,
692  "Inode 0x%llx link count exceeded maximum.  Pinning link count.",
693                                 ip->i_ino);
694         if (inode->i_nlink != XFS_NLINK_PINNED)
695                 inc_nlink(inode);
696 
697         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
698 }
699 
700 /* Free an inode in the ondisk index and zero it out. */
701 int
702 xfs_inode_uninit(
703         struct xfs_trans        *tp,
704         struct xfs_perag        *pag,
705         struct xfs_inode        *ip,
706         struct xfs_icluster     *xic)
707 {
708         struct xfs_mount        *mp = ip->i_mount;
709         int                     error;
710 
711         /*
712          * Free the inode first so that we guarantee that the AGI lock is going
713          * to be taken before we remove the inode from the unlinked list. This
714          * makes the AGI lock -> unlinked list modification order the same as
715          * used in O_TMPFILE creation.
716          */
717         error = xfs_difree(tp, pag, ip->i_ino, xic);
718         if (error)
719                 return error;
720 
721         error = xfs_iunlink_remove(tp, pag, ip);
722         if (error)
723                 return error;
724 
725         /*
726          * Free any local-format data sitting around before we reset the
727          * data fork to extents format.  Note that the attr fork data has
728          * already been freed by xfs_attr_inactive.
729          */
730         if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
731                 kfree(ip->i_df.if_data);
732                 ip->i_df.if_data = NULL;
733                 ip->i_df.if_bytes = 0;
734         }
735 
736         VFS_I(ip)->i_mode = 0;          /* mark incore inode as free */
737         ip->i_diflags = 0;
738         ip->i_diflags2 = mp->m_ino_geo.new_diflags2;
739         ip->i_forkoff = 0;              /* mark the attr fork not in use */
740         ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
741 
742         /*
743          * Bump the generation count so no one will be confused
744          * by reincarnations of this inode.
745          */
746         VFS_I(ip)->i_generation++;
747         xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
748         return 0;
749 }
750 

~ [ 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