aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_dir2.c')
-rw-r--r--fs/xfs/xfs_dir2.c396
1 files changed, 161 insertions, 235 deletions
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 022c8398ab62..8edbe1adb95b 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -24,21 +24,18 @@
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_sb.h" 25#include "xfs_sb.h"
26#include "xfs_ag.h" 26#include "xfs_ag.h"
27#include "xfs_dir.h"
28#include "xfs_dir2.h" 27#include "xfs_dir2.h"
29#include "xfs_dmapi.h" 28#include "xfs_dmapi.h"
30#include "xfs_mount.h" 29#include "xfs_mount.h"
31#include "xfs_da_btree.h" 30#include "xfs_da_btree.h"
32#include "xfs_bmap_btree.h" 31#include "xfs_bmap_btree.h"
33#include "xfs_alloc_btree.h" 32#include "xfs_alloc_btree.h"
34#include "xfs_dir_sf.h"
35#include "xfs_dir2_sf.h" 33#include "xfs_dir2_sf.h"
36#include "xfs_attr_sf.h" 34#include "xfs_attr_sf.h"
37#include "xfs_dinode.h" 35#include "xfs_dinode.h"
38#include "xfs_inode.h" 36#include "xfs_inode.h"
39#include "xfs_inode_item.h" 37#include "xfs_inode_item.h"
40#include "xfs_bmap.h" 38#include "xfs_bmap.h"
41#include "xfs_dir_leaf.h"
42#include "xfs_dir2_data.h" 39#include "xfs_dir2_data.h"
43#include "xfs_dir2_leaf.h" 40#include "xfs_dir2_leaf.h"
44#include "xfs_dir2_block.h" 41#include "xfs_dir2_block.h"
@@ -46,69 +43,14 @@
46#include "xfs_dir2_trace.h" 43#include "xfs_dir2_trace.h"
47#include "xfs_error.h" 44#include "xfs_error.h"
48 45
49/*
50 * Declarations for interface routines.
51 */
52static void xfs_dir2_mount(xfs_mount_t *mp);
53static int xfs_dir2_isempty(xfs_inode_t *dp);
54static int xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp,
55 xfs_inode_t *pdp);
56static int xfs_dir2_createname(xfs_trans_t *tp, xfs_inode_t *dp,
57 char *name, int namelen, xfs_ino_t inum,
58 xfs_fsblock_t *first,
59 xfs_bmap_free_t *flist, xfs_extlen_t total);
60static int xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
61 int namelen, xfs_ino_t *inum);
62static int xfs_dir2_removename(xfs_trans_t *tp, xfs_inode_t *dp,
63 char *name, int namelen, xfs_ino_t ino,
64 xfs_fsblock_t *first,
65 xfs_bmap_free_t *flist, xfs_extlen_t total);
66static int xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio,
67 int *eofp);
68static int xfs_dir2_replace(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
69 int namelen, xfs_ino_t inum,
70 xfs_fsblock_t *first, xfs_bmap_free_t *flist,
71 xfs_extlen_t total);
72static int xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name,
73 int namelen);
74static int xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp,
75 xfs_dinode_t *dip);
76
77/*
78 * Utility routine declarations.
79 */
80static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); 46static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
81static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); 47static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);
82 48
83/* 49void
84 * Directory operations vector. 50xfs_dir_mount(
85 */ 51 xfs_mount_t *mp)
86xfs_dirops_t xfsv2_dirops = {
87 .xd_mount = xfs_dir2_mount,
88 .xd_isempty = xfs_dir2_isempty,
89 .xd_init = xfs_dir2_init,
90 .xd_createname = xfs_dir2_createname,
91 .xd_lookup = xfs_dir2_lookup,
92 .xd_removename = xfs_dir2_removename,
93 .xd_getdents = xfs_dir2_getdents,
94 .xd_replace = xfs_dir2_replace,
95 .xd_canenter = xfs_dir2_canenter,
96 .xd_shortform_validate_ondisk = xfs_dir2_shortform_validate_ondisk,
97 .xd_shortform_to_single = xfs_dir2_sf_to_block,
98};
99
100/*
101 * Interface routines.
102 */
103
104/*
105 * Initialize directory-related fields in the mount structure.
106 */
107static void
108xfs_dir2_mount(
109 xfs_mount_t *mp) /* filesystem mount point */
110{ 52{
111 mp->m_dirversion = 2; 53 ASSERT(XFS_SB_VERSION_HASDIRV2(&mp->m_sb));
112 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= 54 ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <=
113 XFS_MAX_BLOCKSIZE); 55 XFS_MAX_BLOCKSIZE);
114 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); 56 mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog);
@@ -128,19 +70,15 @@ xfs_dir2_mount(
128/* 70/*
129 * Return 1 if directory contains only "." and "..". 71 * Return 1 if directory contains only "." and "..".
130 */ 72 */
131static int /* return code */ 73int
132xfs_dir2_isempty( 74xfs_dir_isempty(
133 xfs_inode_t *dp) /* incore inode structure */ 75 xfs_inode_t *dp)
134{ 76{
135 xfs_dir2_sf_t *sfp; /* shortform directory structure */ 77 xfs_dir2_sf_t *sfp;
136 78
137 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 79 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
138 /* 80 if (dp->i_d.di_size == 0) /* might happen during shutdown. */
139 * Might happen during shutdown.
140 */
141 if (dp->i_d.di_size == 0) {
142 return 1; 81 return 1;
143 }
144 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) 82 if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp))
145 return 0; 83 return 0;
146 sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data; 84 sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data;
@@ -148,53 +86,83 @@ xfs_dir2_isempty(
148} 86}
149 87
150/* 88/*
89 * Validate a given inode number.
90 */
91int
92xfs_dir_ino_validate(
93 xfs_mount_t *mp,
94 xfs_ino_t ino)
95{
96 xfs_agblock_t agblkno;
97 xfs_agino_t agino;
98 xfs_agnumber_t agno;
99 int ino_ok;
100 int ioff;
101
102 agno = XFS_INO_TO_AGNO(mp, ino);
103 agblkno = XFS_INO_TO_AGBNO(mp, ino);
104 ioff = XFS_INO_TO_OFFSET(mp, ino);
105 agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff);
106 ino_ok =
107 agno < mp->m_sb.sb_agcount &&
108 agblkno < mp->m_sb.sb_agblocks &&
109 agblkno != 0 &&
110 ioff < (1 << mp->m_sb.sb_inopblog) &&
111 XFS_AGINO_TO_INO(mp, agno, agino) == ino;
112 if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE,
113 XFS_RANDOM_DIR_INO_VALIDATE))) {
114 xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx",
115 (unsigned long long) ino);
116 XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp);
117 return XFS_ERROR(EFSCORRUPTED);
118 }
119 return 0;
120}
121
122/*
151 * Initialize a directory with its "." and ".." entries. 123 * Initialize a directory with its "." and ".." entries.
152 */ 124 */
153static int /* error */ 125int
154xfs_dir2_init( 126xfs_dir_init(
155 xfs_trans_t *tp, /* transaction pointer */ 127 xfs_trans_t *tp,
156 xfs_inode_t *dp, /* incore directory inode */ 128 xfs_inode_t *dp,
157 xfs_inode_t *pdp) /* incore parent directory inode */ 129 xfs_inode_t *pdp)
158{ 130{
159 xfs_da_args_t args; /* operation arguments */ 131 xfs_da_args_t args;
160 int error; /* error return value */ 132 int error;
161 133
162 memset((char *)&args, 0, sizeof(args)); 134 memset((char *)&args, 0, sizeof(args));
163 args.dp = dp; 135 args.dp = dp;
164 args.trans = tp; 136 args.trans = tp;
165 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 137 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
166 if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) { 138 if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino)))
167 return error; 139 return error;
168 }
169 return xfs_dir2_sf_create(&args, pdp->i_ino); 140 return xfs_dir2_sf_create(&args, pdp->i_ino);
170} 141}
171 142
172/* 143/*
173 Enter a name in a directory. 144 Enter a name in a directory.
174 */ 145 */
175static int /* error */ 146int
176xfs_dir2_createname( 147xfs_dir_createname(
177 xfs_trans_t *tp, /* transaction pointer */ 148 xfs_trans_t *tp,
178 xfs_inode_t *dp, /* incore directory inode */ 149 xfs_inode_t *dp,
179 char *name, /* new entry name */ 150 char *name,
180 int namelen, /* new entry name length */ 151 int namelen,
181 xfs_ino_t inum, /* new entry inode number */ 152 xfs_ino_t inum, /* new entry inode number */
182 xfs_fsblock_t *first, /* bmap's firstblock */ 153 xfs_fsblock_t *first, /* bmap's firstblock */
183 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 154 xfs_bmap_free_t *flist, /* bmap's freeblock list */
184 xfs_extlen_t total) /* bmap's total block count */ 155 xfs_extlen_t total) /* bmap's total block count */
185{ 156{
186 xfs_da_args_t args; /* operation arguments */ 157 xfs_da_args_t args;
187 int rval; /* return value */ 158 int rval;
188 int v; /* type-checking value */ 159 int v; /* type-checking value */
189 160
190 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 161 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
191 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { 162 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
192 return rval; 163 return rval;
193 }
194 XFS_STATS_INC(xs_dir_create); 164 XFS_STATS_INC(xs_dir_create);
195 /* 165
196 * Fill in the arg structure for this request.
197 */
198 args.name = name; 166 args.name = name;
199 args.namelen = namelen; 167 args.namelen = namelen;
200 args.hashval = xfs_da_hashname(name, namelen); 168 args.hashval = xfs_da_hashname(name, namelen);
@@ -207,18 +175,16 @@ xfs_dir2_createname(
207 args.trans = tp; 175 args.trans = tp;
208 args.justcheck = 0; 176 args.justcheck = 0;
209 args.addname = args.oknoent = 1; 177 args.addname = args.oknoent = 1;
210 /* 178
211 * Decide on what work routines to call based on the inode size.
212 */
213 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 179 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
214 rval = xfs_dir2_sf_addname(&args); 180 rval = xfs_dir2_sf_addname(&args);
215 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 181 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
216 return rval; 182 return rval;
217 } else if (v) 183 else if (v)
218 rval = xfs_dir2_block_addname(&args); 184 rval = xfs_dir2_block_addname(&args);
219 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 185 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
220 return rval; 186 return rval;
221 } else if (v) 187 else if (v)
222 rval = xfs_dir2_leaf_addname(&args); 188 rval = xfs_dir2_leaf_addname(&args);
223 else 189 else
224 rval = xfs_dir2_node_addname(&args); 190 rval = xfs_dir2_node_addname(&args);
@@ -228,24 +194,21 @@ xfs_dir2_createname(
228/* 194/*
229 * Lookup a name in a directory, give back the inode number. 195 * Lookup a name in a directory, give back the inode number.
230 */ 196 */
231static int /* error */ 197int
232xfs_dir2_lookup( 198xfs_dir_lookup(
233 xfs_trans_t *tp, /* transaction pointer */ 199 xfs_trans_t *tp,
234 xfs_inode_t *dp, /* incore directory inode */ 200 xfs_inode_t *dp,
235 char *name, /* lookup name */ 201 char *name,
236 int namelen, /* lookup name length */ 202 int namelen,
237 xfs_ino_t *inum) /* out: inode number */ 203 xfs_ino_t *inum) /* out: inode number */
238{ 204{
239 xfs_da_args_t args; /* operation arguments */ 205 xfs_da_args_t args;
240 int rval; /* return value */ 206 int rval;
241 int v; /* type-checking value */ 207 int v; /* type-checking value */
242 208
243 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 209 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
244 XFS_STATS_INC(xs_dir_lookup); 210 XFS_STATS_INC(xs_dir_lookup);
245 211
246 /*
247 * Fill in the arg structure for this request.
248 */
249 args.name = name; 212 args.name = name;
250 args.namelen = namelen; 213 args.namelen = namelen;
251 args.hashval = xfs_da_hashname(name, namelen); 214 args.hashval = xfs_da_hashname(name, namelen);
@@ -258,18 +221,16 @@ xfs_dir2_lookup(
258 args.trans = tp; 221 args.trans = tp;
259 args.justcheck = args.addname = 0; 222 args.justcheck = args.addname = 0;
260 args.oknoent = 1; 223 args.oknoent = 1;
261 /* 224
262 * Decide on what work routines to call based on the inode size.
263 */
264 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 225 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
265 rval = xfs_dir2_sf_lookup(&args); 226 rval = xfs_dir2_sf_lookup(&args);
266 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 227 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
267 return rval; 228 return rval;
268 } else if (v) 229 else if (v)
269 rval = xfs_dir2_block_lookup(&args); 230 rval = xfs_dir2_block_lookup(&args);
270 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 231 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
271 return rval; 232 return rval;
272 } else if (v) 233 else if (v)
273 rval = xfs_dir2_leaf_lookup(&args); 234 rval = xfs_dir2_leaf_lookup(&args);
274 else 235 else
275 rval = xfs_dir2_node_lookup(&args); 236 rval = xfs_dir2_node_lookup(&args);
@@ -283,26 +244,24 @@ xfs_dir2_lookup(
283/* 244/*
284 * Remove an entry from a directory. 245 * Remove an entry from a directory.
285 */ 246 */
286static int /* error */ 247int
287xfs_dir2_removename( 248xfs_dir_removename(
288 xfs_trans_t *tp, /* transaction pointer */ 249 xfs_trans_t *tp,
289 xfs_inode_t *dp, /* incore directory inode */ 250 xfs_inode_t *dp,
290 char *name, /* name of entry to remove */ 251 char *name,
291 int namelen, /* name length of entry to remove */ 252 int namelen,
292 xfs_ino_t ino, /* inode number of entry to remove */ 253 xfs_ino_t ino,
293 xfs_fsblock_t *first, /* bmap's firstblock */ 254 xfs_fsblock_t *first, /* bmap's firstblock */
294 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 255 xfs_bmap_free_t *flist, /* bmap's freeblock list */
295 xfs_extlen_t total) /* bmap's total block count */ 256 xfs_extlen_t total) /* bmap's total block count */
296{ 257{
297 xfs_da_args_t args; /* operation arguments */ 258 xfs_da_args_t args;
298 int rval; /* return value */ 259 int rval;
299 int v; /* type-checking value */ 260 int v; /* type-checking value */
300 261
301 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 262 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
302 XFS_STATS_INC(xs_dir_remove); 263 XFS_STATS_INC(xs_dir_remove);
303 /* 264
304 * Fill in the arg structure for this request.
305 */
306 args.name = name; 265 args.name = name;
307 args.namelen = namelen; 266 args.namelen = namelen;
308 args.hashval = xfs_da_hashname(name, namelen); 267 args.hashval = xfs_da_hashname(name, namelen);
@@ -314,18 +273,16 @@ xfs_dir2_removename(
314 args.whichfork = XFS_DATA_FORK; 273 args.whichfork = XFS_DATA_FORK;
315 args.trans = tp; 274 args.trans = tp;
316 args.justcheck = args.addname = args.oknoent = 0; 275 args.justcheck = args.addname = args.oknoent = 0;
317 /* 276
318 * Decide on what work routines to call based on the inode size.
319 */
320 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 277 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
321 rval = xfs_dir2_sf_removename(&args); 278 rval = xfs_dir2_sf_removename(&args);
322 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 279 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
323 return rval; 280 return rval;
324 } else if (v) 281 else if (v)
325 rval = xfs_dir2_block_removename(&args); 282 rval = xfs_dir2_block_removename(&args);
326 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 283 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
327 return rval; 284 return rval;
328 } else if (v) 285 else if (v)
329 rval = xfs_dir2_leaf_removename(&args); 286 rval = xfs_dir2_leaf_removename(&args);
330 else 287 else
331 rval = xfs_dir2_node_removename(&args); 288 rval = xfs_dir2_node_removename(&args);
@@ -335,10 +292,10 @@ xfs_dir2_removename(
335/* 292/*
336 * Read a directory. 293 * Read a directory.
337 */ 294 */
338static int /* error */ 295int
339xfs_dir2_getdents( 296xfs_dir_getdents(
340 xfs_trans_t *tp, /* transaction pointer */ 297 xfs_trans_t *tp,
341 xfs_inode_t *dp, /* incore directory inode */ 298 xfs_inode_t *dp,
342 uio_t *uio, /* caller's buffer control */ 299 uio_t *uio, /* caller's buffer control */
343 int *eofp) /* out: eof reached */ 300 int *eofp) /* out: eof reached */
344{ 301{
@@ -367,14 +324,11 @@ xfs_dir2_getdents(
367 } 324 }
368 325
369 *eofp = 0; 326 *eofp = 0;
370 /*
371 * Decide on what work routines to call based on the inode size.
372 */
373 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 327 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
374 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put); 328 rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
375 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 329 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
376 ; 330 ;
377 } else if (v) 331 else if (v)
378 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put); 332 rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
379 else 333 else
380 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put); 334 rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
@@ -386,29 +340,26 @@ xfs_dir2_getdents(
386/* 340/*
387 * Replace the inode number of a directory entry. 341 * Replace the inode number of a directory entry.
388 */ 342 */
389static int /* error */ 343int
390xfs_dir2_replace( 344xfs_dir_replace(
391 xfs_trans_t *tp, /* transaction pointer */ 345 xfs_trans_t *tp,
392 xfs_inode_t *dp, /* incore directory inode */ 346 xfs_inode_t *dp,
393 char *name, /* name of entry to replace */ 347 char *name, /* name of entry to replace */
394 int namelen, /* name length of entry to replace */ 348 int namelen,
395 xfs_ino_t inum, /* new inode number */ 349 xfs_ino_t inum, /* new inode number */
396 xfs_fsblock_t *first, /* bmap's firstblock */ 350 xfs_fsblock_t *first, /* bmap's firstblock */
397 xfs_bmap_free_t *flist, /* bmap's freeblock list */ 351 xfs_bmap_free_t *flist, /* bmap's freeblock list */
398 xfs_extlen_t total) /* bmap's total block count */ 352 xfs_extlen_t total) /* bmap's total block count */
399{ 353{
400 xfs_da_args_t args; /* operation arguments */ 354 xfs_da_args_t args;
401 int rval; /* return value */ 355 int rval;
402 int v; /* type-checking value */ 356 int v; /* type-checking value */
403 357
404 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 358 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
405 359
406 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { 360 if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum)))
407 return rval; 361 return rval;
408 } 362
409 /*
410 * Fill in the arg structure for this request.
411 */
412 args.name = name; 363 args.name = name;
413 args.namelen = namelen; 364 args.namelen = namelen;
414 args.hashval = xfs_da_hashname(name, namelen); 365 args.hashval = xfs_da_hashname(name, namelen);
@@ -420,18 +371,16 @@ xfs_dir2_replace(
420 args.whichfork = XFS_DATA_FORK; 371 args.whichfork = XFS_DATA_FORK;
421 args.trans = tp; 372 args.trans = tp;
422 args.justcheck = args.addname = args.oknoent = 0; 373 args.justcheck = args.addname = args.oknoent = 0;
423 /* 374
424 * Decide on what work routines to call based on the inode size.
425 */
426 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 375 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
427 rval = xfs_dir2_sf_replace(&args); 376 rval = xfs_dir2_sf_replace(&args);
428 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 377 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
429 return rval; 378 return rval;
430 } else if (v) 379 else if (v)
431 rval = xfs_dir2_block_replace(&args); 380 rval = xfs_dir2_block_replace(&args);
432 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 381 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
433 return rval; 382 return rval;
434 } else if (v) 383 else if (v)
435 rval = xfs_dir2_leaf_replace(&args); 384 rval = xfs_dir2_leaf_replace(&args);
436 else 385 else
437 rval = xfs_dir2_node_replace(&args); 386 rval = xfs_dir2_node_replace(&args);
@@ -441,21 +390,19 @@ xfs_dir2_replace(
441/* 390/*
442 * See if this entry can be added to the directory without allocating space. 391 * See if this entry can be added to the directory without allocating space.
443 */ 392 */
444static int /* error */ 393int
445xfs_dir2_canenter( 394xfs_dir_canenter(
446 xfs_trans_t *tp, /* transaction pointer */ 395 xfs_trans_t *tp,
447 xfs_inode_t *dp, /* incore directory inode */ 396 xfs_inode_t *dp,
448 char *name, /* name of entry to add */ 397 char *name, /* name of entry to add */
449 int namelen) /* name length of entry to add */ 398 int namelen)
450{ 399{
451 xfs_da_args_t args; /* operation arguments */ 400 xfs_da_args_t args;
452 int rval; /* return value */ 401 int rval;
453 int v; /* type-checking value */ 402 int v; /* type-checking value */
454 403
455 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); 404 ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
456 /* 405
457 * Fill in the arg structure for this request.
458 */
459 args.name = name; 406 args.name = name;
460 args.namelen = namelen; 407 args.namelen = namelen;
461 args.hashval = xfs_da_hashname(name, namelen); 408 args.hashval = xfs_da_hashname(name, namelen);
@@ -467,18 +414,16 @@ xfs_dir2_canenter(
467 args.whichfork = XFS_DATA_FORK; 414 args.whichfork = XFS_DATA_FORK;
468 args.trans = tp; 415 args.trans = tp;
469 args.justcheck = args.addname = args.oknoent = 1; 416 args.justcheck = args.addname = args.oknoent = 1;
470 /* 417
471 * Decide on what work routines to call based on the inode size.
472 */
473 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) 418 if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
474 rval = xfs_dir2_sf_addname(&args); 419 rval = xfs_dir2_sf_addname(&args);
475 else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { 420 else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
476 return rval; 421 return rval;
477 } else if (v) 422 else if (v)
478 rval = xfs_dir2_block_addname(&args); 423 rval = xfs_dir2_block_addname(&args);
479 else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { 424 else if ((rval = xfs_dir2_isleaf(tp, dp, &v)))
480 return rval; 425 return rval;
481 } else if (v) 426 else if (v)
482 rval = xfs_dir2_leaf_addname(&args); 427 rval = xfs_dir2_leaf_addname(&args);
483 else 428 else
484 rval = xfs_dir2_node_addname(&args); 429 rval = xfs_dir2_node_addname(&args);
@@ -486,19 +431,6 @@ xfs_dir2_canenter(
486} 431}
487 432
488/* 433/*
489 * Dummy routine for shortform inode validation.
490 * Can't really do this.
491 */
492/* ARGSUSED */
493static int /* error */
494xfs_dir2_shortform_validate_ondisk(
495 xfs_mount_t *mp, /* filesystem mount point */
496 xfs_dinode_t *dip) /* ondisk inode */
497{
498 return 0;
499}
500
501/*
502 * Utility routines. 434 * Utility routines.
503 */ 435 */
504 436
@@ -507,24 +439,24 @@ xfs_dir2_shortform_validate_ondisk(
507 * This routine is for data and free blocks, not leaf/node blocks 439 * This routine is for data and free blocks, not leaf/node blocks
508 * which are handled by xfs_da_grow_inode. 440 * which are handled by xfs_da_grow_inode.
509 */ 441 */
510int /* error */ 442int
511xfs_dir2_grow_inode( 443xfs_dir2_grow_inode(
512 xfs_da_args_t *args, /* operation arguments */ 444 xfs_da_args_t *args,
513 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ 445 int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */
514 xfs_dir2_db_t *dbp) /* out: block number added */ 446 xfs_dir2_db_t *dbp) /* out: block number added */
515{ 447{
516 xfs_fileoff_t bno; /* directory offset of new block */ 448 xfs_fileoff_t bno; /* directory offset of new block */
517 int count; /* count of filesystem blocks */ 449 int count; /* count of filesystem blocks */
518 xfs_inode_t *dp; /* incore directory inode */ 450 xfs_inode_t *dp; /* incore directory inode */
519 int error; /* error return value */ 451 int error;
520 int got; /* blocks actually mapped */ 452 int got; /* blocks actually mapped */
521 int i; /* temp mapping index */ 453 int i;
522 xfs_bmbt_irec_t map; /* single structure for bmap */ 454 xfs_bmbt_irec_t map; /* single structure for bmap */
523 int mapi; /* mapping index */ 455 int mapi; /* mapping index */
524 xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */ 456 xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */
525 xfs_mount_t *mp; /* filesystem mount point */ 457 xfs_mount_t *mp;
526 int nmap; /* number of bmap entries */ 458 int nmap; /* number of bmap entries */
527 xfs_trans_t *tp; /* transaction pointer */ 459 xfs_trans_t *tp;
528 460
529 xfs_dir2_trace_args_s("grow_inode", args, space); 461 xfs_dir2_trace_args_s("grow_inode", args, space);
530 dp = args->dp; 462 dp = args->dp;
@@ -538,9 +470,8 @@ xfs_dir2_grow_inode(
538 /* 470 /*
539 * Find the first hole for our block. 471 * Find the first hole for our block.
540 */ 472 */
541 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) { 473 if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK)))
542 return error; 474 return error;
543 }
544 nmap = 1; 475 nmap = 1;
545 ASSERT(args->firstblock != NULL); 476 ASSERT(args->firstblock != NULL);
546 /* 477 /*
@@ -549,13 +480,9 @@ xfs_dir2_grow_inode(
549 if ((error = xfs_bmapi(tp, dp, bno, count, 480 if ((error = xfs_bmapi(tp, dp, bno, count,
550 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, 481 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG,
551 args->firstblock, args->total, &map, &nmap, 482 args->firstblock, args->total, &map, &nmap,
552 args->flist))) { 483 args->flist, NULL)))
553 return error; 484 return error;
554 }
555 ASSERT(nmap <= 1); 485 ASSERT(nmap <= 1);
556 /*
557 * Got it in 1.
558 */
559 if (nmap == 1) { 486 if (nmap == 1) {
560 mapp = &map; 487 mapp = &map;
561 mapi = 1; 488 mapi = 1;
@@ -585,7 +512,8 @@ xfs_dir2_grow_inode(
585 if ((error = xfs_bmapi(tp, dp, b, c, 512 if ((error = xfs_bmapi(tp, dp, b, c,
586 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA, 513 XFS_BMAPI_WRITE|XFS_BMAPI_METADATA,
587 args->firstblock, args->total, 514 args->firstblock, args->total,
588 &mapp[mapi], &nmap, args->flist))) { 515 &mapp[mapi], &nmap, args->flist,
516 NULL))) {
589 kmem_free(mapp, sizeof(*mapp) * count); 517 kmem_free(mapp, sizeof(*mapp) * count);
590 return error; 518 return error;
591 } 519 }
@@ -645,20 +573,19 @@ xfs_dir2_grow_inode(
645/* 573/*
646 * See if the directory is a single-block form directory. 574 * See if the directory is a single-block form directory.
647 */ 575 */
648int /* error */ 576int
649xfs_dir2_isblock( 577xfs_dir2_isblock(
650 xfs_trans_t *tp, /* transaction pointer */ 578 xfs_trans_t *tp,
651 xfs_inode_t *dp, /* incore directory inode */ 579 xfs_inode_t *dp,
652 int *vp) /* out: 1 is block, 0 is not block */ 580 int *vp) /* out: 1 is block, 0 is not block */
653{ 581{
654 xfs_fileoff_t last; /* last file offset */ 582 xfs_fileoff_t last; /* last file offset */
655 xfs_mount_t *mp; /* filesystem mount point */ 583 xfs_mount_t *mp;
656 int rval; /* return value */ 584 int rval;
657 585
658 mp = dp->i_mount; 586 mp = dp->i_mount;
659 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { 587 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
660 return rval; 588 return rval;
661 }
662 rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize; 589 rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize;
663 ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize); 590 ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize);
664 *vp = rval; 591 *vp = rval;
@@ -668,20 +595,19 @@ xfs_dir2_isblock(
668/* 595/*
669 * See if the directory is a single-leaf form directory. 596 * See if the directory is a single-leaf form directory.
670 */ 597 */
671int /* error */ 598int
672xfs_dir2_isleaf( 599xfs_dir2_isleaf(
673 xfs_trans_t *tp, /* transaction pointer */ 600 xfs_trans_t *tp,
674 xfs_inode_t *dp, /* incore directory inode */ 601 xfs_inode_t *dp,
675 int *vp) /* out: 1 is leaf, 0 is not leaf */ 602 int *vp) /* out: 1 is leaf, 0 is not leaf */
676{ 603{
677 xfs_fileoff_t last; /* last file offset */ 604 xfs_fileoff_t last; /* last file offset */
678 xfs_mount_t *mp; /* filesystem mount point */ 605 xfs_mount_t *mp;
679 int rval; /* return value */ 606 int rval;
680 607
681 mp = dp->i_mount; 608 mp = dp->i_mount;
682 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { 609 if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK)))
683 return rval; 610 return rval;
684 }
685 *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); 611 *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog);
686 return 0; 612 return 0;
687} 613}
@@ -689,9 +615,9 @@ xfs_dir2_isleaf(
689/* 615/*
690 * Getdents put routine for 64-bit ABI, direct form. 616 * Getdents put routine for 64-bit ABI, direct form.
691 */ 617 */
692static int /* error */ 618static int
693xfs_dir2_put_dirent64_direct( 619xfs_dir2_put_dirent64_direct(
694 xfs_dir2_put_args_t *pa) /* argument bundle */ 620 xfs_dir2_put_args_t *pa)
695{ 621{
696 xfs_dirent_t *idbp; /* dirent pointer */ 622 xfs_dirent_t *idbp; /* dirent pointer */
697 iovec_t *iovp; /* io vector */ 623 iovec_t *iovp; /* io vector */
@@ -726,9 +652,9 @@ xfs_dir2_put_dirent64_direct(
726/* 652/*
727 * Getdents put routine for 64-bit ABI, uio form. 653 * Getdents put routine for 64-bit ABI, uio form.
728 */ 654 */
729static int /* error */ 655static int
730xfs_dir2_put_dirent64_uio( 656xfs_dir2_put_dirent64_uio(
731 xfs_dir2_put_args_t *pa) /* argument bundle */ 657 xfs_dir2_put_args_t *pa)
732{ 658{
733 xfs_dirent_t *idbp; /* dirent pointer */ 659 xfs_dirent_t *idbp; /* dirent pointer */
734 int namelen; /* entry name length */ 660 int namelen; /* entry name length */
@@ -764,17 +690,17 @@ xfs_dir2_put_dirent64_uio(
764 */ 690 */
765int 691int
766xfs_dir2_shrink_inode( 692xfs_dir2_shrink_inode(
767 xfs_da_args_t *args, /* operation arguments */ 693 xfs_da_args_t *args,
768 xfs_dir2_db_t db, /* directory block number */ 694 xfs_dir2_db_t db,
769 xfs_dabuf_t *bp) /* block's buffer */ 695 xfs_dabuf_t *bp)
770{ 696{
771 xfs_fileoff_t bno; /* directory file offset */ 697 xfs_fileoff_t bno; /* directory file offset */
772 xfs_dablk_t da; /* directory file offset */ 698 xfs_dablk_t da; /* directory file offset */
773 int done; /* bunmap is finished */ 699 int done; /* bunmap is finished */
774 xfs_inode_t *dp; /* incore directory inode */ 700 xfs_inode_t *dp;
775 int error; /* error return value */ 701 int error;
776 xfs_mount_t *mp; /* filesystem mount point */ 702 xfs_mount_t *mp;
777 xfs_trans_t *tp; /* transaction pointer */ 703 xfs_trans_t *tp;
778 704
779 xfs_dir2_trace_args_db("shrink_inode", args, db, bp); 705 xfs_dir2_trace_args_db("shrink_inode", args, db, bp);
780 dp = args->dp; 706 dp = args->dp;
@@ -786,7 +712,7 @@ xfs_dir2_shrink_inode(
786 */ 712 */
787 if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, 713 if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs,
788 XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, 714 XFS_BMAPI_METADATA, 0, args->firstblock, args->flist,
789 &done))) { 715 NULL, &done))) {
790 /* 716 /*
791 * ENOSPC actually can happen if we're in a removename with 717 * ENOSPC actually can happen if we're in a removename with
792 * no space reservation, and the resulting block removal 718 * no space reservation, and the resulting block removal