Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: factor the xfs_iunlink functions

Prep work that separates the locking that protects the unlinked list
from the actual operations being performed. This also helps document
the fact they are performing list insert and remove operations. No
functional code change.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>

authored by

Dave Chinner and committed by
Dave Chinner
a4454cd6 04a98a03

+79 -55
+79 -55
fs/xfs/xfs_inode.c
··· 2115 2115 return error; 2116 2116 } 2117 2117 2118 + static int 2119 + xfs_iunlink_insert_inode( 2120 + struct xfs_trans *tp, 2121 + struct xfs_perag *pag, 2122 + struct xfs_buf *agibp, 2123 + struct xfs_inode *ip) 2124 + { 2125 + struct xfs_mount *mp = tp->t_mountp; 2126 + struct xfs_agi *agi = agibp->b_addr; 2127 + xfs_agino_t next_agino; 2128 + xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); 2129 + short bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS; 2130 + int error; 2131 + 2132 + /* 2133 + * Get the index into the agi hash table for the list this inode will 2134 + * go on. Make sure the pointer isn't garbage and that this inode 2135 + * isn't already on the list. 2136 + */ 2137 + next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); 2138 + if (next_agino == agino || 2139 + !xfs_verify_agino_or_null(pag, next_agino)) { 2140 + xfs_buf_mark_corrupt(agibp); 2141 + return -EFSCORRUPTED; 2142 + } 2143 + 2144 + if (next_agino != NULLAGINO) { 2145 + xfs_agino_t old_agino; 2146 + 2147 + /* 2148 + * There is already another inode in the bucket, so point this 2149 + * inode to the current head of the list. 2150 + */ 2151 + error = xfs_iunlink_update_inode(tp, ip, pag, next_agino, 2152 + &old_agino); 2153 + if (error) 2154 + return error; 2155 + ASSERT(old_agino == NULLAGINO); 2156 + 2157 + /* 2158 + * agino has been unlinked, add a backref from the next inode 2159 + * back to agino. 2160 + */ 2161 + error = xfs_iunlink_add_backref(pag, agino, next_agino); 2162 + if (error) 2163 + return error; 2164 + } 2165 + 2166 + /* Point the head of the list to point to this inode. */ 2167 + return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino); 2168 + } 2169 + 2118 2170 /* 2119 2171 * This is called when the inode's link count has gone to 0 or we are creating 2120 2172 * a tmpfile via O_TMPFILE. The inode @ip must have nlink == 0. ··· 2181 2129 { 2182 2130 struct xfs_mount *mp = tp->t_mountp; 2183 2131 struct xfs_perag *pag; 2184 - struct xfs_agi *agi; 2185 2132 struct xfs_buf *agibp; 2186 - xfs_agino_t next_agino; 2187 - xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); 2188 - short bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS; 2189 2133 int error; 2190 2134 2191 2135 ASSERT(VFS_I(ip)->i_nlink == 0); ··· 2194 2146 error = xfs_read_agi(pag, tp, &agibp); 2195 2147 if (error) 2196 2148 goto out; 2197 - agi = agibp->b_addr; 2198 2149 2199 - /* 2200 - * Get the index into the agi hash table for the list this inode will 2201 - * go on. Make sure the pointer isn't garbage and that this inode 2202 - * isn't already on the list. 2203 - */ 2204 - next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); 2205 - if (next_agino == agino || 2206 - !xfs_verify_agino_or_null(pag, next_agino)) { 2207 - xfs_buf_mark_corrupt(agibp); 2208 - error = -EFSCORRUPTED; 2209 - goto out; 2210 - } 2211 - 2212 - if (next_agino != NULLAGINO) { 2213 - xfs_agino_t old_agino; 2214 - 2215 - /* 2216 - * There is already another inode in the bucket, so point this 2217 - * inode to the current head of the list. 2218 - */ 2219 - error = xfs_iunlink_update_inode(tp, ip, pag, next_agino, 2220 - &old_agino); 2221 - if (error) 2222 - goto out; 2223 - ASSERT(old_agino == NULLAGINO); 2224 - 2225 - /* 2226 - * agino has been unlinked, add a backref from the next inode 2227 - * back to agino. 2228 - */ 2229 - error = xfs_iunlink_add_backref(pag, agino, next_agino); 2230 - if (error) 2231 - goto out; 2232 - } 2233 - 2234 - /* Point the head of the list to point to this inode. */ 2235 - error = xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino); 2150 + error = xfs_iunlink_insert_inode(tp, pag, agibp, ip); 2236 2151 out: 2237 2152 xfs_perag_put(pag); 2238 2153 return error; ··· 2316 2305 return 0; 2317 2306 } 2318 2307 2319 - /* 2320 - * Pull the on-disk inode from the AGI unlinked list. 2321 - */ 2322 - STATIC int 2323 - xfs_iunlink_remove( 2308 + static int 2309 + xfs_iunlink_remove_inode( 2324 2310 struct xfs_trans *tp, 2325 2311 struct xfs_perag *pag, 2312 + struct xfs_buf *agibp, 2326 2313 struct xfs_inode *ip) 2327 2314 { 2328 2315 struct xfs_mount *mp = tp->t_mountp; 2329 - struct xfs_agi *agi; 2330 - struct xfs_buf *agibp; 2316 + struct xfs_agi *agi = agibp->b_addr; 2331 2317 struct xfs_buf *last_ibp; 2332 2318 struct xfs_dinode *last_dip = NULL; 2333 2319 xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); ··· 2334 2326 int error; 2335 2327 2336 2328 trace_xfs_iunlink_remove(ip); 2337 - 2338 - /* Get the agi buffer first. It ensures lock ordering on the list. */ 2339 - error = xfs_read_agi(pag, tp, &agibp); 2340 - if (error) 2341 - return error; 2342 - agi = agibp->b_addr; 2343 2329 2344 2330 /* 2345 2331 * Get the index into the agi hash table for the list this inode will ··· 2397 2395 /* Point the head of the list to the next unlinked inode. */ 2398 2396 return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, 2399 2397 next_agino); 2398 + } 2399 + 2400 + /* 2401 + * Pull the on-disk inode from the AGI unlinked list. 2402 + */ 2403 + STATIC int 2404 + xfs_iunlink_remove( 2405 + struct xfs_trans *tp, 2406 + struct xfs_perag *pag, 2407 + struct xfs_inode *ip) 2408 + { 2409 + struct xfs_buf *agibp; 2410 + int error; 2411 + 2412 + trace_xfs_iunlink_remove(ip); 2413 + 2414 + /* Get the agi buffer first. It ensures lock ordering on the list. */ 2415 + error = xfs_read_agi(pag, tp, &agibp); 2416 + if (error) 2417 + return error; 2418 + 2419 + return xfs_iunlink_remove_inode(tp, pag, agibp, ip); 2400 2420 } 2401 2421 2402 2422 /*