aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_da_btree.h1
-rw-r--r--fs/xfs/xfs_dir2.c5
-rw-r--r--fs/xfs/xfs_dir2.h4
-rw-r--r--fs/xfs/xfs_dir2_block.c16
-rw-r--r--fs/xfs/xfs_dir2_data.c13
-rw-r--r--fs/xfs/xfs_dir2_format.h183
-rw-r--r--fs/xfs/xfs_dir2_leaf.c6
-rw-r--r--fs/xfs/xfs_dir2_node.c8
-rw-r--r--fs/xfs/xfs_dir2_priv.h9
-rw-r--r--fs/xfs/xfs_dir2_readdir.c69
-rw-r--r--fs/xfs/xfs_dir2_sf.c121
-rw-r--r--fs/xfs/xfs_iops.c27
-rw-r--r--fs/xfs/xfs_sb.h22
-rw-r--r--fs/xfs/xfs_types.h1
14 files changed, 362 insertions, 123 deletions
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h
index 6fb3371c63cf..8cdc77b2e58d 100644
--- a/fs/xfs/xfs_da_btree.h
+++ b/fs/xfs/xfs_da_btree.h
@@ -176,6 +176,7 @@ enum xfs_dacmp {
176typedef struct xfs_da_args { 176typedef struct xfs_da_args {
177 const __uint8_t *name; /* string (maybe not NULL terminated) */ 177 const __uint8_t *name; /* string (maybe not NULL terminated) */
178 int namelen; /* length of string (maybe no NULL) */ 178 int namelen; /* length of string (maybe no NULL) */
179 __uint8_t filetype; /* filetype of inode for directories */
179 __uint8_t *value; /* set of bytes (maybe contain NULLs) */ 180 __uint8_t *value; /* set of bytes (maybe contain NULLs) */
180 int valuelen; /* length of value */ 181 int valuelen; /* length of value */
181 int flags; /* argument flags (eg: ATTR_NOCREATE) */ 182 int flags; /* argument flags (eg: ATTR_NOCREATE) */
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c
index 841933c9e80f..f9825b125fcf 100644
--- a/fs/xfs/xfs_dir2.c
+++ b/fs/xfs/xfs_dir2.c
@@ -37,7 +37,8 @@
37#include "xfs_error.h" 37#include "xfs_error.h"
38#include "xfs_trace.h" 38#include "xfs_trace.h"
39 39
40struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2}; 40struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
41
41 42
42/* 43/*
43 * ASCII case-insensitive (ie. A-Z) support for directories that was 44 * ASCII case-insensitive (ie. A-Z) support for directories that was
@@ -386,6 +387,7 @@ xfs_dir_replace(
386 memset(&args, 0, sizeof(xfs_da_args_t)); 387 memset(&args, 0, sizeof(xfs_da_args_t));
387 args.name = name->name; 388 args.name = name->name;
388 args.namelen = name->len; 389 args.namelen = name->len;
390 args.filetype = name->type;
389 args.hashval = dp->i_mount->m_dirnameops->hashname(name); 391 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
390 args.inumber = inum; 392 args.inumber = inum;
391 args.dp = dp; 393 args.dp = dp;
@@ -433,6 +435,7 @@ xfs_dir_canenter(
433 memset(&args, 0, sizeof(xfs_da_args_t)); 435 memset(&args, 0, sizeof(xfs_da_args_t));
434 args.name = name->name; 436 args.name = name->name;
435 args.namelen = name->len; 437 args.namelen = name->len;
438 args.filetype = name->type;
436 args.hashval = dp->i_mount->m_dirnameops->hashname(name); 439 args.hashval = dp->i_mount->m_dirnameops->hashname(name);
437 args.dp = dp; 440 args.dp = dp;
438 args.whichfork = XFS_DATA_FORK; 441 args.whichfork = XFS_DATA_FORK;
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h
index 7fe2b8f0a9e3..768ddad41b84 100644
--- a/fs/xfs/xfs_dir2.h
+++ b/fs/xfs/xfs_dir2.h
@@ -68,8 +68,8 @@ extern int xfs_dir2_sf_to_block(struct xfs_da_args *args);
68extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp); 68extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp);
69extern void xfs_dir2_sf_put_parent_ino(struct xfs_dir2_sf_hdr *sfp, 69extern void xfs_dir2_sf_put_parent_ino(struct xfs_dir2_sf_hdr *sfp,
70 xfs_ino_t ino); 70 xfs_ino_t ino);
71extern xfs_ino_t xfs_dir2_sfe_get_ino(struct xfs_dir2_sf_hdr *sfp, 71extern xfs_ino_t xfs_dir3_sfe_get_ino(struct xfs_mount *mp,
72 struct xfs_dir2_sf_entry *sfep); 72 struct xfs_dir2_sf_hdr *sfp, struct xfs_dir2_sf_entry *sfep);
73extern void xfs_dir2_sfe_put_ino( struct xfs_dir2_sf_hdr *, 73extern void xfs_dir2_sfe_put_ino( struct xfs_dir2_sf_hdr *,
74 struct xfs_dir2_sf_entry *sfep, xfs_ino_t ino); 74 struct xfs_dir2_sf_entry *sfep, xfs_ino_t ino);
75 75
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index becd69f6e4b8..1cd2f564e374 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -369,7 +369,7 @@ xfs_dir2_block_addname(
369 if (error) 369 if (error)
370 return error; 370 return error;
371 371
372 len = xfs_dir2_data_entsize(args->namelen); 372 len = xfs_dir3_data_entsize(mp, args->namelen);
373 373
374 /* 374 /*
375 * Set up pointers to parts of the block. 375 * Set up pointers to parts of the block.
@@ -549,7 +549,7 @@ xfs_dir2_block_addname(
549 dep->inumber = cpu_to_be64(args->inumber); 549 dep->inumber = cpu_to_be64(args->inumber);
550 dep->namelen = args->namelen; 550 dep->namelen = args->namelen;
551 memcpy(dep->name, args->name, args->namelen); 551 memcpy(dep->name, args->name, args->namelen);
552 tagp = xfs_dir2_data_entry_tag_p(dep); 552 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
553 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 553 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
554 /* 554 /*
555 * Clean up the bestfree array and log the header, tail, and entry. 555 * Clean up the bestfree array and log the header, tail, and entry.
@@ -799,7 +799,7 @@ xfs_dir2_block_removename(
799 needlog = needscan = 0; 799 needlog = needscan = 0;
800 xfs_dir2_data_make_free(tp, bp, 800 xfs_dir2_data_make_free(tp, bp,
801 (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), 801 (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
802 xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan); 802 xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan);
803 /* 803 /*
804 * Fix up the block tail. 804 * Fix up the block tail.
805 */ 805 */
@@ -1159,7 +1159,7 @@ xfs_dir2_sf_to_block(
1159 dep->inumber = cpu_to_be64(dp->i_ino); 1159 dep->inumber = cpu_to_be64(dp->i_ino);
1160 dep->namelen = 1; 1160 dep->namelen = 1;
1161 dep->name[0] = '.'; 1161 dep->name[0] = '.';
1162 tagp = xfs_dir2_data_entry_tag_p(dep); 1162 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
1163 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1163 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
1164 xfs_dir2_data_log_entry(tp, bp, dep); 1164 xfs_dir2_data_log_entry(tp, bp, dep);
1165 blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot); 1165 blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
@@ -1172,7 +1172,7 @@ xfs_dir2_sf_to_block(
1172 dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp)); 1172 dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));
1173 dep->namelen = 2; 1173 dep->namelen = 2;
1174 dep->name[0] = dep->name[1] = '.'; 1174 dep->name[0] = dep->name[1] = '.';
1175 tagp = xfs_dir2_data_entry_tag_p(dep); 1175 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
1176 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1176 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
1177 xfs_dir2_data_log_entry(tp, bp, dep); 1177 xfs_dir2_data_log_entry(tp, bp, dep);
1178 blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); 1178 blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
@@ -1217,10 +1217,10 @@ xfs_dir2_sf_to_block(
1217 * Copy a real entry. 1217 * Copy a real entry.
1218 */ 1218 */
1219 dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset); 1219 dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset);
1220 dep->inumber = cpu_to_be64(xfs_dir2_sfe_get_ino(sfp, sfep)); 1220 dep->inumber = cpu_to_be64(xfs_dir3_sfe_get_ino(mp, sfp, sfep));
1221 dep->namelen = sfep->namelen; 1221 dep->namelen = sfep->namelen;
1222 memcpy(dep->name, sfep->name, dep->namelen); 1222 memcpy(dep->name, sfep->name, dep->namelen);
1223 tagp = xfs_dir2_data_entry_tag_p(dep); 1223 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
1224 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 1224 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
1225 xfs_dir2_data_log_entry(tp, bp, dep); 1225 xfs_dir2_data_log_entry(tp, bp, dep);
1226 name.name = sfep->name; 1226 name.name = sfep->name;
@@ -1233,7 +1233,7 @@ xfs_dir2_sf_to_block(
1233 if (++i == sfp->count) 1233 if (++i == sfp->count)
1234 sfep = NULL; 1234 sfep = NULL;
1235 else 1235 else
1236 sfep = xfs_dir2_sf_nextentry(sfp, sfep); 1236 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
1237 } 1237 }
1238 /* Done with the temporary buffer */ 1238 /* Done with the temporary buffer */
1239 kmem_free(sfp); 1239 kmem_free(sfp);
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index 98c23faa701c..1b59e43d97d9 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -147,7 +147,7 @@ __xfs_dir3_data_check(
147 XFS_WANT_CORRUPTED_RETURN( 147 XFS_WANT_CORRUPTED_RETURN(
148 !xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber))); 148 !xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)));
149 XFS_WANT_CORRUPTED_RETURN( 149 XFS_WANT_CORRUPTED_RETURN(
150 be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep)) == 150 be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) ==
151 (char *)dep - (char *)hdr); 151 (char *)dep - (char *)hdr);
152 count++; 152 count++;
153 lastfree = 0; 153 lastfree = 0;
@@ -166,7 +166,7 @@ __xfs_dir3_data_check(
166 } 166 }
167 XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count)); 167 XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count));
168 } 168 }
169 p += xfs_dir2_data_entsize(dep->namelen); 169 p += xfs_dir3_data_entsize(mp, dep->namelen);
170 } 170 }
171 /* 171 /*
172 * Need to have seen all the entries and all the bestfree slots. 172 * Need to have seen all the entries and all the bestfree slots.
@@ -536,8 +536,8 @@ xfs_dir2_data_freescan(
536 else { 536 else {
537 dep = (xfs_dir2_data_entry_t *)p; 537 dep = (xfs_dir2_data_entry_t *)p;
538 ASSERT((char *)dep - (char *)hdr == 538 ASSERT((char *)dep - (char *)hdr ==
539 be16_to_cpu(*xfs_dir2_data_entry_tag_p(dep))); 539 be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)));
540 p += xfs_dir2_data_entsize(dep->namelen); 540 p += xfs_dir3_data_entsize(mp, dep->namelen);
541 } 541 }
542 } 542 }
543} 543}
@@ -627,7 +627,8 @@ xfs_dir2_data_log_entry(
627 struct xfs_buf *bp, 627 struct xfs_buf *bp,
628 xfs_dir2_data_entry_t *dep) /* data entry pointer */ 628 xfs_dir2_data_entry_t *dep) /* data entry pointer */
629{ 629{
630 xfs_dir2_data_hdr_t *hdr = bp->b_addr; 630 struct xfs_dir2_data_hdr *hdr = bp->b_addr;
631 struct xfs_mount *mp = tp->t_mountp;
631 632
632 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 633 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
633 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || 634 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
@@ -635,7 +636,7 @@ xfs_dir2_data_log_entry(
635 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)); 636 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
636 637
637 xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr), 638 xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
638 (uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) - 639 (uint)((char *)(xfs_dir3_data_entry_tag_p(mp, dep) + 1) -
639 (char *)hdr - 1)); 640 (char *)hdr - 1));
640} 641}
641 642
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h
index 2095e17b75cb..a0961a61ac1a 100644
--- a/fs/xfs/xfs_dir2_format.h
+++ b/fs/xfs/xfs_dir2_format.h
@@ -69,6 +69,23 @@
69#define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */ 69#define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */
70 70
71/* 71/*
72 * Dirents in version 3 directories have a file type field. Additions to this
73 * list are an on-disk format change, requiring feature bits. Valid values
74 * are as follows:
75 */
76#define XFS_DIR3_FT_UNKNOWN 0
77#define XFS_DIR3_FT_REG_FILE 1
78#define XFS_DIR3_FT_DIR 2
79#define XFS_DIR3_FT_CHRDEV 3
80#define XFS_DIR3_FT_BLKDEV 4
81#define XFS_DIR3_FT_FIFO 5
82#define XFS_DIR3_FT_SOCK 6
83#define XFS_DIR3_FT_SYMLINK 7
84#define XFS_DIR3_FT_WHT 8
85
86#define XFS_DIR3_FT_MAX 9
87
88/*
72 * Byte offset in data block and shortform entry. 89 * Byte offset in data block and shortform entry.
73 */ 90 */
74typedef __uint16_t xfs_dir2_data_off_t; 91typedef __uint16_t xfs_dir2_data_off_t;
@@ -138,6 +155,9 @@ typedef struct xfs_dir2_sf_entry {
138 xfs_dir2_sf_off_t offset; /* saved offset */ 155 xfs_dir2_sf_off_t offset; /* saved offset */
139 __u8 name[]; /* name, variable size */ 156 __u8 name[]; /* name, variable size */
140 /* 157 /*
158 * A single byte containing the file type field follows the inode
159 * number for version 3 directory entries.
160 *
141 * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a 161 * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a
142 * variable offset after the name. 162 * variable offset after the name.
143 */ 163 */
@@ -162,16 +182,6 @@ xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off)
162 put_unaligned_be16(off, &sfep->offset.i); 182 put_unaligned_be16(off, &sfep->offset.i);
163} 183}
164 184
165static inline int
166xfs_dir2_sf_entsize(struct xfs_dir2_sf_hdr *hdr, int len)
167{
168 return sizeof(struct xfs_dir2_sf_entry) + /* namelen + offset */
169 len + /* name */
170 (hdr->i8count ? /* ino */
171 sizeof(xfs_dir2_ino8_t) :
172 sizeof(xfs_dir2_ino4_t));
173}
174
175static inline struct xfs_dir2_sf_entry * 185static inline struct xfs_dir2_sf_entry *
176xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) 186xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
177{ 187{
@@ -179,14 +189,78 @@ xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr)
179 ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count)); 189 ((char *)hdr + xfs_dir2_sf_hdr_size(hdr->i8count));
180} 190}
181 191
192static inline int
193xfs_dir3_sf_entsize(
194 struct xfs_mount *mp,
195 struct xfs_dir2_sf_hdr *hdr,
196 int len)
197{
198 int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */
199
200 count += len; /* name */
201 count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) :
202 sizeof(xfs_dir2_ino4_t); /* ino # */
203 if (xfs_sb_version_hasftype(&mp->m_sb))
204 count += sizeof(__uint8_t); /* file type */
205 return count;
206}
207
182static inline struct xfs_dir2_sf_entry * 208static inline struct xfs_dir2_sf_entry *
183xfs_dir2_sf_nextentry(struct xfs_dir2_sf_hdr *hdr, 209xfs_dir3_sf_nextentry(
184 struct xfs_dir2_sf_entry *sfep) 210 struct xfs_mount *mp,
211 struct xfs_dir2_sf_hdr *hdr,
212 struct xfs_dir2_sf_entry *sfep)
185{ 213{
186 return (struct xfs_dir2_sf_entry *) 214 return (struct xfs_dir2_sf_entry *)
187 ((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen)); 215 ((char *)sfep + xfs_dir3_sf_entsize(mp, hdr, sfep->namelen));
188} 216}
189 217
218/*
219 * in dir3 shortform directories, the file type field is stored at a variable
220 * offset after the inode number. Because it's only a single byte, endian
221 * conversion is not necessary.
222 */
223static inline __uint8_t *
224xfs_dir3_sfe_ftypep(
225 struct xfs_dir2_sf_hdr *hdr,
226 struct xfs_dir2_sf_entry *sfep)
227{
228 return (__uint8_t *)&sfep->name[sfep->namelen];
229}
230
231static inline __uint8_t
232xfs_dir3_sfe_get_ftype(
233 struct xfs_mount *mp,
234 struct xfs_dir2_sf_hdr *hdr,
235 struct xfs_dir2_sf_entry *sfep)
236{
237 __uint8_t *ftp;
238
239 if (!xfs_sb_version_hasftype(&mp->m_sb))
240 return XFS_DIR3_FT_UNKNOWN;
241
242 ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
243 if (*ftp >= XFS_DIR3_FT_MAX)
244 return XFS_DIR3_FT_UNKNOWN;
245 return *ftp;
246}
247
248static inline void
249xfs_dir3_sfe_put_ftype(
250 struct xfs_mount *mp,
251 struct xfs_dir2_sf_hdr *hdr,
252 struct xfs_dir2_sf_entry *sfep,
253 __uint8_t ftype)
254{
255 __uint8_t *ftp;
256
257 ASSERT(ftype < XFS_DIR3_FT_MAX);
258
259 if (!xfs_sb_version_hasftype(&mp->m_sb))
260 return;
261 ftp = xfs_dir3_sfe_ftypep(hdr, sfep);
262 *ftp = ftype;
263}
190 264
191/* 265/*
192 * Data block structures. 266 * Data block structures.
@@ -286,12 +360,18 @@ xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
286 * Active entry in a data block. 360 * Active entry in a data block.
287 * 361 *
288 * Aligned to 8 bytes. After the variable length name field there is a 362 * Aligned to 8 bytes. After the variable length name field there is a
289 * 2 byte tag field, which can be accessed using xfs_dir2_data_entry_tag_p. 363 * 2 byte tag field, which can be accessed using xfs_dir3_data_entry_tag_p.
364 *
365 * For dir3 structures, there is file type field between the name and the tag.
366 * This can only be manipulated by helper functions. It is packed hard against
367 * the end of the name so any padding for rounding is between the file type and
368 * the tag.
290 */ 369 */
291typedef struct xfs_dir2_data_entry { 370typedef struct xfs_dir2_data_entry {
292 __be64 inumber; /* inode number */ 371 __be64 inumber; /* inode number */
293 __u8 namelen; /* name length */ 372 __u8 namelen; /* name length */
294 __u8 name[]; /* name bytes, no null */ 373 __u8 name[]; /* name bytes, no null */
374 /* __u8 filetype; */ /* type of inode we point to */
295 /* __be16 tag; */ /* starting offset of us */ 375 /* __be16 tag; */ /* starting offset of us */
296} xfs_dir2_data_entry_t; 376} xfs_dir2_data_entry_t;
297 377
@@ -311,20 +391,67 @@ typedef struct xfs_dir2_data_unused {
311/* 391/*
312 * Size of a data entry. 392 * Size of a data entry.
313 */ 393 */
314static inline int xfs_dir2_data_entsize(int n) 394static inline int
395__xfs_dir3_data_entsize(
396 bool ftype,
397 int n)
315{ 398{
316 return (int)roundup(offsetof(struct xfs_dir2_data_entry, name[0]) + n + 399 int size = offsetof(struct xfs_dir2_data_entry, name[0]);
317 (uint)sizeof(xfs_dir2_data_off_t), XFS_DIR2_DATA_ALIGN); 400
401 size += n;
402 size += sizeof(xfs_dir2_data_off_t);
403 if (ftype)
404 size += sizeof(__uint8_t);
405 return roundup(size, XFS_DIR2_DATA_ALIGN);
406}
407static inline int
408xfs_dir3_data_entsize(
409 struct xfs_mount *mp,
410 int n)
411{
412 bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false;
413 return __xfs_dir3_data_entsize(ftype, n);
414}
415
416static inline __uint8_t
417xfs_dir3_dirent_get_ftype(
418 struct xfs_mount *mp,
419 struct xfs_dir2_data_entry *dep)
420{
421 if (xfs_sb_version_hasftype(&mp->m_sb)) {
422 __uint8_t type = dep->name[dep->namelen];
423
424 ASSERT(type < XFS_DIR3_FT_MAX);
425 if (type < XFS_DIR3_FT_MAX)
426 return type;
427
428 }
429 return XFS_DIR3_FT_UNKNOWN;
430}
431
432static inline void
433xfs_dir3_dirent_put_ftype(
434 struct xfs_mount *mp,
435 struct xfs_dir2_data_entry *dep,
436 __uint8_t type)
437{
438 ASSERT(type < XFS_DIR3_FT_MAX);
439 ASSERT(dep->namelen != 0);
440
441 if (xfs_sb_version_hasftype(&mp->m_sb))
442 dep->name[dep->namelen] = type;
318} 443}
319 444
320/* 445/*
321 * Pointer to an entry's tag word. 446 * Pointer to an entry's tag word.
322 */ 447 */
323static inline __be16 * 448static inline __be16 *
324xfs_dir2_data_entry_tag_p(struct xfs_dir2_data_entry *dep) 449xfs_dir3_data_entry_tag_p(
450 struct xfs_mount *mp,
451 struct xfs_dir2_data_entry *dep)
325{ 452{
326 return (__be16 *)((char *)dep + 453 return (__be16 *)((char *)dep +
327 xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16)); 454 xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16));
328} 455}
329 456
330/* 457/*
@@ -375,13 +502,17 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
375 * data block header because the sfe embeds the block offset of the entry into 502 * data block header because the sfe embeds the block offset of the entry into
376 * it so that it doesn't change when format conversion occurs. Bad Things Happen 503 * it so that it doesn't change when format conversion occurs. Bad Things Happen
377 * if we don't follow this rule. 504 * if we don't follow this rule.
505 *
506 * XXX: there is scope for significant optimisation of the logic here. Right
507 * now we are checking for "dir3 format" over and over again. Ideally we should
508 * only do it once for each operation.
378 */ 509 */
379#define XFS_DIR3_DATA_DOT_OFFSET(mp) \ 510#define XFS_DIR3_DATA_DOT_OFFSET(mp) \
380 xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&(mp)->m_sb)) 511 xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&(mp)->m_sb))
381#define XFS_DIR3_DATA_DOTDOT_OFFSET(mp) \ 512#define XFS_DIR3_DATA_DOTDOT_OFFSET(mp) \
382 (XFS_DIR3_DATA_DOT_OFFSET(mp) + xfs_dir2_data_entsize(1)) 513 (XFS_DIR3_DATA_DOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 1))
383#define XFS_DIR3_DATA_FIRST_OFFSET(mp) \ 514#define XFS_DIR3_DATA_FIRST_OFFSET(mp) \
384 (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir2_data_entsize(2)) 515 (XFS_DIR3_DATA_DOTDOT_OFFSET(mp) + xfs_dir3_data_entsize(mp, 2))
385 516
386static inline xfs_dir2_data_aoff_t 517static inline xfs_dir2_data_aoff_t
387xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr) 518xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr)
@@ -392,13 +523,19 @@ xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr)
392static inline xfs_dir2_data_aoff_t 523static inline xfs_dir2_data_aoff_t
393xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr) 524xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr)
394{ 525{
395 return xfs_dir3_data_dot_offset(hdr) + xfs_dir2_data_entsize(1); 526 bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
527 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
528 return xfs_dir3_data_dot_offset(hdr) +
529 __xfs_dir3_data_entsize(dir3, 1);
396} 530}
397 531
398static inline xfs_dir2_data_aoff_t 532static inline xfs_dir2_data_aoff_t
399xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr) 533xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr)
400{ 534{
401 return xfs_dir3_data_dotdot_offset(hdr) + xfs_dir2_data_entsize(2); 535 bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
536 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
537 return xfs_dir3_data_dotdot_offset(hdr) +
538 __xfs_dir3_data_entsize(dir3, 2);
402} 539}
403 540
404/* 541/*
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 591eaf235919..887b1bdec6dd 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -696,7 +696,7 @@ xfs_dir2_leaf_addname(
696 ents = xfs_dir3_leaf_ents_p(leaf); 696 ents = xfs_dir3_leaf_ents_p(leaf);
697 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf); 697 xfs_dir3_leaf_hdr_from_disk(&leafhdr, leaf);
698 bestsp = xfs_dir2_leaf_bests_p(ltp); 698 bestsp = xfs_dir2_leaf_bests_p(ltp);
699 length = xfs_dir2_data_entsize(args->namelen); 699 length = xfs_dir3_data_entsize(mp, args->namelen);
700 700
701 /* 701 /*
702 * See if there are any entries with the same hash value 702 * See if there are any entries with the same hash value
@@ -897,7 +897,7 @@ xfs_dir2_leaf_addname(
897 dep->inumber = cpu_to_be64(args->inumber); 897 dep->inumber = cpu_to_be64(args->inumber);
898 dep->namelen = args->namelen; 898 dep->namelen = args->namelen;
899 memcpy(dep->name, args->name, dep->namelen); 899 memcpy(dep->name, args->name, dep->namelen);
900 tagp = xfs_dir2_data_entry_tag_p(dep); 900 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
901 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 901 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
902 /* 902 /*
903 * Need to scan fix up the bestfree table. 903 * Need to scan fix up the bestfree table.
@@ -1427,7 +1427,7 @@ xfs_dir2_leaf_removename(
1427 */ 1427 */
1428 xfs_dir2_data_make_free(tp, dbp, 1428 xfs_dir2_data_make_free(tp, dbp,
1429 (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr), 1429 (xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
1430 xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan); 1430 xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan);
1431 /* 1431 /*
1432 * We just mark the leaf entry stale by putting a null in it. 1432 * We just mark the leaf entry stale by putting a null in it.
1433 */ 1433 */
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 18e287deee66..49f1e9ed492c 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -605,7 +605,7 @@ xfs_dir2_leafn_lookup_for_addname(
605 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || 605 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
606 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); 606 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
607 } 607 }
608 length = xfs_dir2_data_entsize(args->namelen); 608 length = xfs_dir3_data_entsize(mp, args->namelen);
609 /* 609 /*
610 * Loop over leaf entries with the right hash value. 610 * Loop over leaf entries with the right hash value.
611 */ 611 */
@@ -1259,7 +1259,7 @@ xfs_dir2_leafn_remove(
1259 longest = be16_to_cpu(bf[0].length); 1259 longest = be16_to_cpu(bf[0].length);
1260 needlog = needscan = 0; 1260 needlog = needscan = 0;
1261 xfs_dir2_data_make_free(tp, dbp, off, 1261 xfs_dir2_data_make_free(tp, dbp, off,
1262 xfs_dir2_data_entsize(dep->namelen), &needlog, &needscan); 1262 xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan);
1263 /* 1263 /*
1264 * Rescan the data block freespaces for bestfree. 1264 * Rescan the data block freespaces for bestfree.
1265 * Log the data block header if needed. 1265 * Log the data block header if needed.
@@ -1711,7 +1711,7 @@ xfs_dir2_node_addname_int(
1711 dp = args->dp; 1711 dp = args->dp;
1712 mp = dp->i_mount; 1712 mp = dp->i_mount;
1713 tp = args->trans; 1713 tp = args->trans;
1714 length = xfs_dir2_data_entsize(args->namelen); 1714 length = xfs_dir3_data_entsize(mp, args->namelen);
1715 /* 1715 /*
1716 * If we came in with a freespace block that means that lookup 1716 * If we came in with a freespace block that means that lookup
1717 * found an entry with our hash value. This is the freespace 1717 * found an entry with our hash value. This is the freespace
@@ -2007,7 +2007,7 @@ xfs_dir2_node_addname_int(
2007 dep->inumber = cpu_to_be64(args->inumber); 2007 dep->inumber = cpu_to_be64(args->inumber);
2008 dep->namelen = args->namelen; 2008 dep->namelen = args->namelen;
2009 memcpy(dep->name, args->name, dep->namelen); 2009 memcpy(dep->name, args->name, dep->namelen);
2010 tagp = xfs_dir2_data_entry_tag_p(dep); 2010 tagp = xfs_dir3_data_entry_tag_p(mp, dep);
2011 *tagp = cpu_to_be16((char *)dep - (char *)hdr); 2011 *tagp = cpu_to_be16((char *)dep - (char *)hdr);
2012 xfs_dir2_data_log_entry(tp, dbp, dep); 2012 xfs_dir2_data_log_entry(tp, dbp, dep);
2013 /* 2013 /*
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h
index 6d2a99c224b7..1bad84c40829 100644
--- a/fs/xfs/xfs_dir2_priv.h
+++ b/fs/xfs/xfs_dir2_priv.h
@@ -18,6 +18,8 @@
18#ifndef __XFS_DIR2_PRIV_H__ 18#ifndef __XFS_DIR2_PRIV_H__
19#define __XFS_DIR2_PRIV_H__ 19#define __XFS_DIR2_PRIV_H__
20 20
21struct dir_context;
22
21/* xfs_dir2.c */ 23/* xfs_dir2.c */
22extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); 24extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
23extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, 25extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
@@ -25,6 +27,13 @@ extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space,
25extern int xfs_dir_cilookup_result(struct xfs_da_args *args, 27extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
26 const unsigned char *name, int len); 28 const unsigned char *name, int len);
27 29
30#define S_SHIFT 12
31extern const unsigned char xfs_mode_to_ftype[];
32
33extern unsigned char xfs_dir3_get_dtype(struct xfs_mount *mp,
34 __uint8_t filetype);
35
36
28/* xfs_dir2_block.c */ 37/* xfs_dir2_block.c */
29extern int xfs_dir3_block_read(struct xfs_trans *tp, struct xfs_inode *dp, 38extern int xfs_dir3_block_read(struct xfs_trans *tp, struct xfs_inode *dp,
30 struct xfs_buf **bpp); 39 struct xfs_buf **bpp);
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
index 5f4f705eebbb..8993ec17452c 100644
--- a/fs/xfs/xfs_dir2_readdir.c
+++ b/fs/xfs/xfs_dir2_readdir.c
@@ -36,6 +36,44 @@
36#include "xfs_trace.h" 36#include "xfs_trace.h"
37#include "xfs_bmap.h" 37#include "xfs_bmap.h"
38 38
39/*
40 * Directory file type support functions
41 */
42static unsigned char xfs_dir3_filetype_table[] = {
43 DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK,
44 DT_FIFO, DT_SOCK, DT_LNK, DT_WHT,
45};
46
47unsigned char
48xfs_dir3_get_dtype(
49 struct xfs_mount *mp,
50 __uint8_t filetype)
51{
52 if (!xfs_sb_version_hasftype(&mp->m_sb))
53 return DT_UNKNOWN;
54
55 if (filetype >= XFS_DIR3_FT_MAX)
56 return DT_UNKNOWN;
57
58 return xfs_dir3_filetype_table[filetype];
59}
60/*
61 * @mode, if set, indicates that the type field needs to be set up.
62 * This uses the transformation from file mode to DT_* as defined in linux/fs.h
63 * for file type specification. This will be propagated into the directory
64 * structure if appropriate for the given operation and filesystem config.
65 */
66const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = {
67 [0] = XFS_DIR3_FT_UNKNOWN,
68 [S_IFREG >> S_SHIFT] = XFS_DIR3_FT_REG_FILE,
69 [S_IFDIR >> S_SHIFT] = XFS_DIR3_FT_DIR,
70 [S_IFCHR >> S_SHIFT] = XFS_DIR3_FT_CHRDEV,
71 [S_IFBLK >> S_SHIFT] = XFS_DIR3_FT_BLKDEV,
72 [S_IFIFO >> S_SHIFT] = XFS_DIR3_FT_FIFO,
73 [S_IFSOCK >> S_SHIFT] = XFS_DIR3_FT_SOCK,
74 [S_IFLNK >> S_SHIFT] = XFS_DIR3_FT_SYMLINK,
75};
76
39STATIC int 77STATIC int
40xfs_dir2_sf_getdents( 78xfs_dir2_sf_getdents(
41 xfs_inode_t *dp, /* incore directory inode */ 79 xfs_inode_t *dp, /* incore directory inode */
@@ -109,20 +147,23 @@ xfs_dir2_sf_getdents(
109 */ 147 */
110 sfep = xfs_dir2_sf_firstentry(sfp); 148 sfep = xfs_dir2_sf_firstentry(sfp);
111 for (i = 0; i < sfp->count; i++) { 149 for (i = 0; i < sfp->count; i++) {
150 __uint8_t filetype;
151
112 off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 152 off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
113 xfs_dir2_sf_get_offset(sfep)); 153 xfs_dir2_sf_get_offset(sfep));
114 154
115 if (ctx->pos > off) { 155 if (ctx->pos > off) {
116 sfep = xfs_dir2_sf_nextentry(sfp, sfep); 156 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
117 continue; 157 continue;
118 } 158 }
119 159
120 ino = xfs_dir2_sfe_get_ino(sfp, sfep); 160 ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep);
161 filetype = xfs_dir3_sfe_get_ftype(mp, sfp, sfep);
121 ctx->pos = off & 0x7fffffff; 162 ctx->pos = off & 0x7fffffff;
122 if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, 163 if (!dir_emit(ctx, (char *)sfep->name, sfep->namelen, ino,
123 ino, DT_UNKNOWN)) 164 xfs_dir3_get_dtype(mp, filetype)))
124 return 0; 165 return 0;
125 sfep = xfs_dir2_sf_nextentry(sfp, sfep); 166 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
126 } 167 }
127 168
128 ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) & 169 ctx->pos = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk + 1, 0) &
@@ -180,6 +221,8 @@ xfs_dir2_block_getdents(
180 * Each object is a real entry (dep) or an unused one (dup). 221 * Each object is a real entry (dep) or an unused one (dup).
181 */ 222 */
182 while (ptr < endptr) { 223 while (ptr < endptr) {
224 __uint8_t filetype;
225
183 dup = (xfs_dir2_data_unused_t *)ptr; 226 dup = (xfs_dir2_data_unused_t *)ptr;
184 /* 227 /*
185 * Unused, skip it. 228 * Unused, skip it.
@@ -194,7 +237,7 @@ xfs_dir2_block_getdents(
194 /* 237 /*
195 * Bump pointer for the next iteration. 238 * Bump pointer for the next iteration.
196 */ 239 */
197 ptr += xfs_dir2_data_entsize(dep->namelen); 240 ptr += xfs_dir3_data_entsize(mp, dep->namelen);
198 /* 241 /*
199 * The entry is before the desired starting point, skip it. 242 * The entry is before the desired starting point, skip it.
200 */ 243 */
@@ -205,11 +248,13 @@ xfs_dir2_block_getdents(
205 (char *)dep - (char *)hdr); 248 (char *)dep - (char *)hdr);
206 249
207 ctx->pos = cook & 0x7fffffff; 250 ctx->pos = cook & 0x7fffffff;
251 filetype = xfs_dir3_dirent_get_ftype(mp, dep);
208 /* 252 /*
209 * If it didn't fit, set the final offset to here & return. 253 * If it didn't fit, set the final offset to here & return.
210 */ 254 */
211 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, 255 if (!dir_emit(ctx, (char *)dep->name, dep->namelen,
212 be64_to_cpu(dep->inumber), DT_UNKNOWN)) { 256 be64_to_cpu(dep->inumber),
257 xfs_dir3_get_dtype(mp, filetype))) {
213 xfs_trans_brelse(NULL, bp); 258 xfs_trans_brelse(NULL, bp);
214 return 0; 259 return 0;
215 } 260 }
@@ -500,6 +545,8 @@ xfs_dir2_leaf_getdents(
500 * Get more blocks and readahead as necessary. 545 * Get more blocks and readahead as necessary.
501 */ 546 */
502 while (curoff < XFS_DIR2_LEAF_OFFSET) { 547 while (curoff < XFS_DIR2_LEAF_OFFSET) {
548 __uint8_t filetype;
549
503 /* 550 /*
504 * If we have no buffer, or we're off the end of the 551 * If we have no buffer, or we're off the end of the
505 * current buffer, need to get another one. 552 * current buffer, need to get another one.
@@ -554,7 +601,7 @@ xfs_dir2_leaf_getdents(
554 } 601 }
555 dep = (xfs_dir2_data_entry_t *)ptr; 602 dep = (xfs_dir2_data_entry_t *)ptr;
556 length = 603 length =
557 xfs_dir2_data_entsize(dep->namelen); 604 xfs_dir3_data_entsize(mp, dep->namelen);
558 ptr += length; 605 ptr += length;
559 } 606 }
560 /* 607 /*
@@ -585,11 +632,13 @@ xfs_dir2_leaf_getdents(
585 } 632 }
586 633
587 dep = (xfs_dir2_data_entry_t *)ptr; 634 dep = (xfs_dir2_data_entry_t *)ptr;
588 length = xfs_dir2_data_entsize(dep->namelen); 635 length = xfs_dir3_data_entsize(mp, dep->namelen);
636 filetype = xfs_dir3_dirent_get_ftype(mp, dep);
589 637
590 ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff; 638 ctx->pos = xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff;
591 if (!dir_emit(ctx, (char *)dep->name, dep->namelen, 639 if (!dir_emit(ctx, (char *)dep->name, dep->namelen,
592 be64_to_cpu(dep->inumber), DT_UNKNOWN)) 640 be64_to_cpu(dep->inumber),
641 xfs_dir3_get_dtype(mp, filetype)))
593 break; 642 break;
594 643
595 /* 644 /*
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index 65b65c5f8c3c..bd14e1a72c62 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -105,31 +105,38 @@ xfs_dir2_sf_put_parent_ino(
105 105
106/* 106/*
107 * In short-form directory entries the inode numbers are stored at variable 107 * In short-form directory entries the inode numbers are stored at variable
108 * offset behind the entry name. The inode numbers may only be accessed 108 * offset behind the entry name. If the entry stores a filetype value, then it
109 * through the helpers below. 109 * sits between the name and the inode number. Hence the inode numbers may only
110 * be accessed through the helpers below.
110 */ 111 */
111static xfs_dir2_inou_t * 112static xfs_dir2_inou_t *
112xfs_dir2_sfe_inop( 113xfs_dir3_sfe_inop(
114 struct xfs_mount *mp,
113 struct xfs_dir2_sf_entry *sfep) 115 struct xfs_dir2_sf_entry *sfep)
114{ 116{
115 return (xfs_dir2_inou_t *)&sfep->name[sfep->namelen]; 117 __uint8_t *ptr = &sfep->name[sfep->namelen];
118 if (xfs_sb_version_hasftype(&mp->m_sb))
119 ptr++;
120 return (xfs_dir2_inou_t *)ptr;
116} 121}
117 122
118xfs_ino_t 123xfs_ino_t
119xfs_dir2_sfe_get_ino( 124xfs_dir3_sfe_get_ino(
125 struct xfs_mount *mp,
120 struct xfs_dir2_sf_hdr *hdr, 126 struct xfs_dir2_sf_hdr *hdr,
121 struct xfs_dir2_sf_entry *sfep) 127 struct xfs_dir2_sf_entry *sfep)
122{ 128{
123 return xfs_dir2_sf_get_ino(hdr, xfs_dir2_sfe_inop(sfep)); 129 return xfs_dir2_sf_get_ino(hdr, xfs_dir3_sfe_inop(mp, sfep));
124} 130}
125 131
126void 132void
127xfs_dir2_sfe_put_ino( 133xfs_dir3_sfe_put_ino(
134 struct xfs_mount *mp,
128 struct xfs_dir2_sf_hdr *hdr, 135 struct xfs_dir2_sf_hdr *hdr,
129 struct xfs_dir2_sf_entry *sfep, 136 struct xfs_dir2_sf_entry *sfep,
130 xfs_ino_t ino) 137 xfs_ino_t ino)
131{ 138{
132 xfs_dir2_sf_put_ino(hdr, xfs_dir2_sfe_inop(sfep), ino); 139 xfs_dir2_sf_put_ino(hdr, xfs_dir3_sfe_inop(mp, sfep), ino);
133} 140}
134 141
135/* 142/*
@@ -157,9 +164,16 @@ xfs_dir2_block_sfsize(
157 int namelen; /* total name bytes */ 164 int namelen; /* total name bytes */
158 xfs_ino_t parent = 0; /* parent inode number */ 165 xfs_ino_t parent = 0; /* parent inode number */
159 int size=0; /* total computed size */ 166 int size=0; /* total computed size */
167 int has_ftype;
160 168
161 mp = dp->i_mount; 169 mp = dp->i_mount;
162 170
171 /*
172 * if there is a filetype field, add the extra byte to the namelen
173 * for each entry that we see.
174 */
175 has_ftype = xfs_sb_version_hasftype(&mp->m_sb) ? 1 : 0;
176
163 count = i8count = namelen = 0; 177 count = i8count = namelen = 0;
164 btp = xfs_dir2_block_tail_p(mp, hdr); 178 btp = xfs_dir2_block_tail_p(mp, hdr);
165 blp = xfs_dir2_block_leaf_p(btp); 179 blp = xfs_dir2_block_leaf_p(btp);
@@ -188,9 +202,10 @@ xfs_dir2_block_sfsize(
188 if (!isdot) 202 if (!isdot)
189 i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM; 203 i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM;
190#endif 204#endif
205 /* take into account the file type field */
191 if (!isdot && !isdotdot) { 206 if (!isdot && !isdotdot) {
192 count++; 207 count++;
193 namelen += dep->namelen; 208 namelen += dep->namelen + has_ftype;
194 } else if (isdotdot) 209 } else if (isdotdot)
195 parent = be64_to_cpu(dep->inumber); 210 parent = be64_to_cpu(dep->inumber);
196 /* 211 /*
@@ -316,12 +331,12 @@ xfs_dir2_block_to_sf(
316 (xfs_dir2_data_aoff_t) 331 (xfs_dir2_data_aoff_t)
317 ((char *)dep - (char *)hdr)); 332 ((char *)dep - (char *)hdr));
318 memcpy(sfep->name, dep->name, dep->namelen); 333 memcpy(sfep->name, dep->name, dep->namelen);
319 xfs_dir2_sfe_put_ino(sfp, sfep, 334 xfs_dir3_sfe_put_ino(mp, sfp, sfep,
320 be64_to_cpu(dep->inumber)); 335 be64_to_cpu(dep->inumber));
321 336
322 sfep = xfs_dir2_sf_nextentry(sfp, sfep); 337 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
323 } 338 }
324 ptr += xfs_dir2_data_entsize(dep->namelen); 339 ptr += xfs_dir3_data_entsize(mp, dep->namelen);
325 } 340 }
326 ASSERT((char *)sfep - (char *)sfp == size); 341 ASSERT((char *)sfep - (char *)sfp == size);
327 xfs_dir2_sf_check(args); 342 xfs_dir2_sf_check(args);
@@ -372,7 +387,7 @@ xfs_dir2_sf_addname(
372 /* 387 /*
373 * Compute entry (and change in) size. 388 * Compute entry (and change in) size.
374 */ 389 */
375 add_entsize = xfs_dir2_sf_entsize(sfp, args->namelen); 390 add_entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen);
376 incr_isize = add_entsize; 391 incr_isize = add_entsize;
377 objchange = 0; 392 objchange = 0;
378#if XFS_BIG_INUMS 393#if XFS_BIG_INUMS
@@ -466,8 +481,9 @@ xfs_dir2_sf_addname_easy(
466 /* 481 /*
467 * Grow the in-inode space. 482 * Grow the in-inode space.
468 */ 483 */
469 xfs_idata_realloc(dp, xfs_dir2_sf_entsize(sfp, args->namelen), 484 xfs_idata_realloc(dp,
470 XFS_DATA_FORK); 485 xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen),
486 XFS_DATA_FORK);
471 /* 487 /*
472 * Need to set up again due to realloc of the inode data. 488 * Need to set up again due to realloc of the inode data.
473 */ 489 */
@@ -479,7 +495,7 @@ xfs_dir2_sf_addname_easy(
479 sfep->namelen = args->namelen; 495 sfep->namelen = args->namelen;
480 xfs_dir2_sf_put_offset(sfep, offset); 496 xfs_dir2_sf_put_offset(sfep, offset);
481 memcpy(sfep->name, args->name, sfep->namelen); 497 memcpy(sfep->name, args->name, sfep->namelen);
482 xfs_dir2_sfe_put_ino(sfp, sfep, args->inumber); 498 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep, args->inumber);
483 /* 499 /*
484 * Update the header and inode. 500 * Update the header and inode.
485 */ 501 */
@@ -519,11 +535,13 @@ xfs_dir2_sf_addname_hard(
519 xfs_dir2_sf_hdr_t *oldsfp; /* original shortform dir */ 535 xfs_dir2_sf_hdr_t *oldsfp; /* original shortform dir */
520 xfs_dir2_sf_entry_t *sfep; /* entry in new dir */ 536 xfs_dir2_sf_entry_t *sfep; /* entry in new dir */
521 xfs_dir2_sf_hdr_t *sfp; /* new shortform dir */ 537 xfs_dir2_sf_hdr_t *sfp; /* new shortform dir */
538 struct xfs_mount *mp;
522 539
523 /* 540 /*
524 * Copy the old directory to the stack buffer. 541 * Copy the old directory to the stack buffer.
525 */ 542 */
526 dp = args->dp; 543 dp = args->dp;
544 mp = dp->i_mount;
527 545
528 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 546 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
529 old_isize = (int)dp->i_d.di_size; 547 old_isize = (int)dp->i_d.di_size;
@@ -535,13 +553,13 @@ xfs_dir2_sf_addname_hard(
535 * to insert the new entry. 553 * to insert the new entry.
536 * If it's going to end up at the end then oldsfep will point there. 554 * If it's going to end up at the end then oldsfep will point there.
537 */ 555 */
538 for (offset = XFS_DIR3_DATA_FIRST_OFFSET(dp->i_mount), 556 for (offset = XFS_DIR3_DATA_FIRST_OFFSET(mp),
539 oldsfep = xfs_dir2_sf_firstentry(oldsfp), 557 oldsfep = xfs_dir2_sf_firstentry(oldsfp),
540 add_datasize = xfs_dir2_data_entsize(args->namelen), 558 add_datasize = xfs_dir3_data_entsize(mp, args->namelen),
541 eof = (char *)oldsfep == &buf[old_isize]; 559 eof = (char *)oldsfep == &buf[old_isize];
542 !eof; 560 !eof;
543 offset = new_offset + xfs_dir2_data_entsize(oldsfep->namelen), 561 offset = new_offset + xfs_dir3_data_entsize(mp, oldsfep->namelen),
544 oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep), 562 oldsfep = xfs_dir3_sf_nextentry(mp, oldsfp, oldsfep),
545 eof = (char *)oldsfep == &buf[old_isize]) { 563 eof = (char *)oldsfep == &buf[old_isize]) {
546 new_offset = xfs_dir2_sf_get_offset(oldsfep); 564 new_offset = xfs_dir2_sf_get_offset(oldsfep);
547 if (offset + add_datasize <= new_offset) 565 if (offset + add_datasize <= new_offset)
@@ -570,7 +588,7 @@ xfs_dir2_sf_addname_hard(
570 sfep->namelen = args->namelen; 588 sfep->namelen = args->namelen;
571 xfs_dir2_sf_put_offset(sfep, offset); 589 xfs_dir2_sf_put_offset(sfep, offset);
572 memcpy(sfep->name, args->name, sfep->namelen); 590 memcpy(sfep->name, args->name, sfep->namelen);
573 xfs_dir2_sfe_put_ino(sfp, sfep, args->inumber); 591 xfs_dir3_sfe_put_ino(mp, sfp, sfep, args->inumber);
574 sfp->count++; 592 sfp->count++;
575#if XFS_BIG_INUMS 593#if XFS_BIG_INUMS
576 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange) 594 if (args->inumber > XFS_DIR2_MAX_SHORT_INUM && !objchange)
@@ -580,7 +598,7 @@ xfs_dir2_sf_addname_hard(
580 * If there's more left to copy, do that. 598 * If there's more left to copy, do that.
581 */ 599 */
582 if (!eof) { 600 if (!eof) {
583 sfep = xfs_dir2_sf_nextentry(sfp, sfep); 601 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
584 memcpy(sfep, oldsfep, old_isize - nbytes); 602 memcpy(sfep, oldsfep, old_isize - nbytes);
585 } 603 }
586 kmem_free(buf); 604 kmem_free(buf);
@@ -616,7 +634,7 @@ xfs_dir2_sf_addname_pick(
616 mp = dp->i_mount; 634 mp = dp->i_mount;
617 635
618 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 636 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
619 size = xfs_dir2_data_entsize(args->namelen); 637 size = xfs_dir3_data_entsize(mp, args->namelen);
620 offset = XFS_DIR3_DATA_FIRST_OFFSET(mp); 638 offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
621 sfep = xfs_dir2_sf_firstentry(sfp); 639 sfep = xfs_dir2_sf_firstentry(sfp);
622 holefit = 0; 640 holefit = 0;
@@ -629,8 +647,8 @@ xfs_dir2_sf_addname_pick(
629 if (!holefit) 647 if (!holefit)
630 holefit = offset + size <= xfs_dir2_sf_get_offset(sfep); 648 holefit = offset + size <= xfs_dir2_sf_get_offset(sfep);
631 offset = xfs_dir2_sf_get_offset(sfep) + 649 offset = xfs_dir2_sf_get_offset(sfep) +
632 xfs_dir2_data_entsize(sfep->namelen); 650 xfs_dir3_data_entsize(mp, sfep->namelen);
633 sfep = xfs_dir2_sf_nextentry(sfp, sfep); 651 sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep);
634 } 652 }
635 /* 653 /*
636 * Calculate data bytes used excluding the new entry, if this 654 * Calculate data bytes used excluding the new entry, if this
@@ -684,31 +702,34 @@ xfs_dir2_sf_check(
684 int offset; /* data offset */ 702 int offset; /* data offset */
685 xfs_dir2_sf_entry_t *sfep; /* shortform dir entry */ 703 xfs_dir2_sf_entry_t *sfep; /* shortform dir entry */
686 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */ 704 xfs_dir2_sf_hdr_t *sfp; /* shortform structure */
705 struct xfs_mount *mp;
687 706
688 dp = args->dp; 707 dp = args->dp;
708 mp = dp->i_mount;
689 709
690 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data; 710 sfp = (xfs_dir2_sf_hdr_t *)dp->i_df.if_u1.if_data;
691 offset = XFS_DIR3_DATA_FIRST_OFFSET(dp->i_mount); 711 offset = XFS_DIR3_DATA_FIRST_OFFSET(mp);
692 ino = xfs_dir2_sf_get_parent_ino(sfp); 712 ino = xfs_dir2_sf_get_parent_ino(sfp);
693 i8count = ino > XFS_DIR2_MAX_SHORT_INUM; 713 i8count = ino > XFS_DIR2_MAX_SHORT_INUM;
694 714
695 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); 715 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp);
696 i < sfp->count; 716 i < sfp->count;
697 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { 717 i++, sfep = xfs_dir3_sf_nextentry(mp, sfp, sfep)) {
698 ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset); 718 ASSERT(xfs_dir2_sf_get_offset(sfep) >= offset);
699 ino = xfs_dir2_sfe_get_ino(sfp, sfep); 719 ino = xfs_dir3_sfe_get_ino(mp, sfp, sfep);
700 i8count += ino > XFS_DIR2_MAX_SHORT_INUM; 720 i8count += ino > XFS_DIR2_MAX_SHORT_INUM;
701 offset = 721 offset =
702 xfs_dir2_sf_get_offset(sfep) + 722 xfs_dir2_sf_get_offset(sfep) +
703 xfs_dir2_data_entsize(sfep->namelen); 723 xfs_dir3_data_entsize(mp, sfep->namelen);
724 ASSERT(xfs_dir3_sfe_get_ftype(mp, sfp, sfep) <
725 XFS_DIR3_FT_MAX);
704 } 726 }
705 ASSERT(i8count == sfp->i8count); 727 ASSERT(i8count == sfp->i8count);
706 ASSERT(XFS_BIG_INUMS || i8count == 0); 728 ASSERT(XFS_BIG_INUMS || i8count == 0);
707 ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size); 729 ASSERT((char *)sfep - (char *)sfp == dp->i_d.di_size);
708 ASSERT(offset + 730 ASSERT(offset +
709 (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) + 731 (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t) +
710 (uint)sizeof(xfs_dir2_block_tail_t) <= 732 (uint)sizeof(xfs_dir2_block_tail_t) <= mp->m_dirblksize);
711 dp->i_mount->m_dirblksize);
712} 733}
713#endif /* DEBUG */ 734#endif /* DEBUG */
714 735
@@ -820,7 +841,7 @@ xfs_dir2_sf_lookup(
820 */ 841 */
821 ci_sfep = NULL; 842 ci_sfep = NULL;
822 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; 843 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
823 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { 844 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) {
824 /* 845 /*
825 * Compare name and if it's an exact match, return the inode 846 * Compare name and if it's an exact match, return the inode
826 * number. If it's the first case-insensitive match, store the 847 * number. If it's the first case-insensitive match, store the
@@ -830,7 +851,8 @@ xfs_dir2_sf_lookup(
830 sfep->namelen); 851 sfep->namelen);
831 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { 852 if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
832 args->cmpresult = cmp; 853 args->cmpresult = cmp;
833 args->inumber = xfs_dir2_sfe_get_ino(sfp, sfep); 854 args->inumber = xfs_dir3_sfe_get_ino(dp->i_mount,
855 sfp, sfep);
834 if (cmp == XFS_CMP_EXACT) 856 if (cmp == XFS_CMP_EXACT)
835 return XFS_ERROR(EEXIST); 857 return XFS_ERROR(EEXIST);
836 ci_sfep = sfep; 858 ci_sfep = sfep;
@@ -886,10 +908,10 @@ xfs_dir2_sf_removename(
886 * Find the one we're deleting. 908 * Find the one we're deleting.
887 */ 909 */
888 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count; 910 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
889 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) { 911 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) {
890 if (xfs_da_compname(args, sfep->name, sfep->namelen) == 912 if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
891 XFS_CMP_EXACT) { 913 XFS_CMP_EXACT) {
892 ASSERT(xfs_dir2_sfe_get_ino(sfp, sfep) == 914 ASSERT(xfs_dir3_sfe_get_ino(dp->i_mount, sfp, sfep) ==
893 args->inumber); 915 args->inumber);
894 break; 916 break;
895 } 917 }
@@ -903,7 +925,7 @@ xfs_dir2_sf_removename(
903 * Calculate sizes. 925 * Calculate sizes.
904 */ 926 */
905 byteoff = (int)((char *)sfep - (char *)sfp); 927 byteoff = (int)((char *)sfep - (char *)sfp);
906 entsize = xfs_dir2_sf_entsize(sfp, args->namelen); 928 entsize = xfs_dir3_sf_entsize(dp->i_mount, sfp, args->namelen);
907 newsize = oldsize - entsize; 929 newsize = oldsize - entsize;
908 /* 930 /*
909 * Copy the part if any after the removed entry, sliding it down. 931 * Copy the part if any after the removed entry, sliding it down.
@@ -1019,16 +1041,17 @@ xfs_dir2_sf_replace(
1019 * Normal entry, look for the name. 1041 * Normal entry, look for the name.
1020 */ 1042 */
1021 else { 1043 else {
1022 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); 1044 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp); i < sfp->count;
1023 i < sfp->count; 1045 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep)) {
1024 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep)) {
1025 if (xfs_da_compname(args, sfep->name, sfep->namelen) == 1046 if (xfs_da_compname(args, sfep->name, sfep->namelen) ==
1026 XFS_CMP_EXACT) { 1047 XFS_CMP_EXACT) {
1027#if XFS_BIG_INUMS || defined(DEBUG) 1048#if XFS_BIG_INUMS || defined(DEBUG)
1028 ino = xfs_dir2_sfe_get_ino(sfp, sfep); 1049 ino = xfs_dir3_sfe_get_ino(dp->i_mount,
1050 sfp, sfep);
1029 ASSERT(args->inumber != ino); 1051 ASSERT(args->inumber != ino);
1030#endif 1052#endif
1031 xfs_dir2_sfe_put_ino(sfp, sfep, args->inumber); 1053 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep,
1054 args->inumber);
1032 break; 1055 break;
1033 } 1056 }
1034 } 1057 }
@@ -1136,13 +1159,13 @@ xfs_dir2_sf_toino4(
1136 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), 1159 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
1137 oldsfep = xfs_dir2_sf_firstentry(oldsfp); 1160 oldsfep = xfs_dir2_sf_firstentry(oldsfp);
1138 i < sfp->count; 1161 i < sfp->count;
1139 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep), 1162 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep),
1140 oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) { 1163 oldsfep = xfs_dir3_sf_nextentry(dp->i_mount, oldsfp, oldsfep)) {
1141 sfep->namelen = oldsfep->namelen; 1164 sfep->namelen = oldsfep->namelen;
1142 sfep->offset = oldsfep->offset; 1165 sfep->offset = oldsfep->offset;
1143 memcpy(sfep->name, oldsfep->name, sfep->namelen); 1166 memcpy(sfep->name, oldsfep->name, sfep->namelen);
1144 xfs_dir2_sfe_put_ino(sfp, sfep, 1167 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep,
1145 xfs_dir2_sfe_get_ino(oldsfp, oldsfep)); 1168 xfs_dir3_sfe_get_ino(dp->i_mount, oldsfp, oldsfep));
1146 } 1169 }
1147 /* 1170 /*
1148 * Clean up the inode. 1171 * Clean up the inode.
@@ -1211,13 +1234,13 @@ xfs_dir2_sf_toino8(
1211 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp), 1234 for (i = 0, sfep = xfs_dir2_sf_firstentry(sfp),
1212 oldsfep = xfs_dir2_sf_firstentry(oldsfp); 1235 oldsfep = xfs_dir2_sf_firstentry(oldsfp);
1213 i < sfp->count; 1236 i < sfp->count;
1214 i++, sfep = xfs_dir2_sf_nextentry(sfp, sfep), 1237 i++, sfep = xfs_dir3_sf_nextentry(dp->i_mount, sfp, sfep),
1215 oldsfep = xfs_dir2_sf_nextentry(oldsfp, oldsfep)) { 1238 oldsfep = xfs_dir3_sf_nextentry(dp->i_mount, oldsfp, oldsfep)) {
1216 sfep->namelen = oldsfep->namelen; 1239 sfep->namelen = oldsfep->namelen;
1217 sfep->offset = oldsfep->offset; 1240 sfep->offset = oldsfep->offset;
1218 memcpy(sfep->name, oldsfep->name, sfep->namelen); 1241 memcpy(sfep->name, oldsfep->name, sfep->namelen);
1219 xfs_dir2_sfe_put_ino(sfp, sfep, 1242 xfs_dir3_sfe_put_ino(dp->i_mount, sfp, sfep,
1220 xfs_dir2_sfe_get_ino(oldsfp, oldsfep)); 1243 xfs_dir3_sfe_get_ino(dp->i_mount, oldsfp, oldsfep));
1221 } 1244 }
1222 /* 1245 /*
1223 * Clean up the inode. 1246 * Clean up the inode.
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 6d7e9e2d7651..2b8952d9199b 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -40,6 +40,9 @@
40#include "xfs_trace.h" 40#include "xfs_trace.h"
41#include "xfs_icache.h" 41#include "xfs_icache.h"
42#include "xfs_symlink.h" 42#include "xfs_symlink.h"
43#include "xfs_da_btree.h"
44#include "xfs_dir2_format.h"
45#include "xfs_dir2_priv.h"
43 46
44#include <linux/capability.h> 47#include <linux/capability.h>
45#include <linux/xattr.h> 48#include <linux/xattr.h>
@@ -88,10 +91,12 @@ xfs_init_security(
88static void 91static void
89xfs_dentry_to_name( 92xfs_dentry_to_name(
90 struct xfs_name *namep, 93 struct xfs_name *namep,
91 struct dentry *dentry) 94 struct dentry *dentry,
95 int mode)
92{ 96{
93 namep->name = dentry->d_name.name; 97 namep->name = dentry->d_name.name;
94 namep->len = dentry->d_name.len; 98 namep->len = dentry->d_name.len;
99 namep->type = xfs_mode_to_ftype[(mode & S_IFMT) >> S_SHIFT];
95} 100}
96 101
97STATIC void 102STATIC void
@@ -107,7 +112,7 @@ xfs_cleanup_inode(
107 * xfs_init_security we must back out. 112 * xfs_init_security we must back out.
108 * ENOSPC can hit here, among other things. 113 * ENOSPC can hit here, among other things.
109 */ 114 */
110 xfs_dentry_to_name(&teardown, dentry); 115 xfs_dentry_to_name(&teardown, dentry, 0);
111 116
112 xfs_remove(XFS_I(dir), &teardown, XFS_I(inode)); 117 xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
113 iput(inode); 118 iput(inode);
@@ -147,7 +152,7 @@ xfs_vn_mknod(
147 mode &= ~current_umask(); 152 mode &= ~current_umask();
148 } 153 }
149 154
150 xfs_dentry_to_name(&name, dentry); 155 xfs_dentry_to_name(&name, dentry, mode);
151 error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip); 156 error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
152 if (unlikely(error)) 157 if (unlikely(error))
153 goto out_free_acl; 158 goto out_free_acl;
@@ -208,7 +213,7 @@ xfs_vn_lookup(
208 if (dentry->d_name.len >= MAXNAMELEN) 213 if (dentry->d_name.len >= MAXNAMELEN)
209 return ERR_PTR(-ENAMETOOLONG); 214 return ERR_PTR(-ENAMETOOLONG);
210 215
211 xfs_dentry_to_name(&name, dentry); 216 xfs_dentry_to_name(&name, dentry, 0);
212 error = xfs_lookup(XFS_I(dir), &name, &cip, NULL); 217 error = xfs_lookup(XFS_I(dir), &name, &cip, NULL);
213 if (unlikely(error)) { 218 if (unlikely(error)) {
214 if (unlikely(error != ENOENT)) 219 if (unlikely(error != ENOENT))
@@ -235,7 +240,7 @@ xfs_vn_ci_lookup(
235 if (dentry->d_name.len >= MAXNAMELEN) 240 if (dentry->d_name.len >= MAXNAMELEN)
236 return ERR_PTR(-ENAMETOOLONG); 241 return ERR_PTR(-ENAMETOOLONG);
237 242
238 xfs_dentry_to_name(&xname, dentry); 243 xfs_dentry_to_name(&xname, dentry, 0);
239 error = xfs_lookup(XFS_I(dir), &xname, &ip, &ci_name); 244 error = xfs_lookup(XFS_I(dir), &xname, &ip, &ci_name);
240 if (unlikely(error)) { 245 if (unlikely(error)) {
241 if (unlikely(error != ENOENT)) 246 if (unlikely(error != ENOENT))
@@ -270,7 +275,7 @@ xfs_vn_link(
270 struct xfs_name name; 275 struct xfs_name name;
271 int error; 276 int error;
272 277
273 xfs_dentry_to_name(&name, dentry); 278 xfs_dentry_to_name(&name, dentry, inode->i_mode);
274 279
275 error = xfs_link(XFS_I(dir), XFS_I(inode), &name); 280 error = xfs_link(XFS_I(dir), XFS_I(inode), &name);
276 if (unlikely(error)) 281 if (unlikely(error))
@@ -289,7 +294,7 @@ xfs_vn_unlink(
289 struct xfs_name name; 294 struct xfs_name name;
290 int error; 295 int error;
291 296
292 xfs_dentry_to_name(&name, dentry); 297 xfs_dentry_to_name(&name, dentry, 0);
293 298
294 error = -xfs_remove(XFS_I(dir), &name, XFS_I(dentry->d_inode)); 299 error = -xfs_remove(XFS_I(dir), &name, XFS_I(dentry->d_inode));
295 if (error) 300 if (error)
@@ -319,7 +324,7 @@ xfs_vn_symlink(
319 324
320 mode = S_IFLNK | 325 mode = S_IFLNK |
321 (irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO); 326 (irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO);
322 xfs_dentry_to_name(&name, dentry); 327 xfs_dentry_to_name(&name, dentry, mode);
323 328
324 error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip); 329 error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip);
325 if (unlikely(error)) 330 if (unlikely(error))
@@ -351,12 +356,12 @@ xfs_vn_rename(
351 struct xfs_name oname; 356 struct xfs_name oname;
352 struct xfs_name nname; 357 struct xfs_name nname;
353 358
354 xfs_dentry_to_name(&oname, odentry); 359 xfs_dentry_to_name(&oname, odentry, 0);
355 xfs_dentry_to_name(&nname, ndentry); 360 xfs_dentry_to_name(&nname, ndentry, odentry->d_inode->i_mode);
356 361
357 return -xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode), 362 return -xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode),
358 XFS_I(ndir), &nname, new_inode ? 363 XFS_I(ndir), &nname, new_inode ?
359 XFS_I(new_inode) : NULL); 364 XFS_I(new_inode) : NULL);
360} 365}
361 366
362/* 367/*
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index db7593f4bc7e..3c297a451622 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -555,12 +555,6 @@ static inline void xfs_sb_version_addprojid32bit(xfs_sb_t *sbp)
555 sbp->sb_bad_features2 |= XFS_SB_VERSION2_PROJID32BIT; 555 sbp->sb_bad_features2 |= XFS_SB_VERSION2_PROJID32BIT;
556} 556}
557 557
558static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp)
559{
560 return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
561}
562
563
564/* 558/*
565 * Extended v5 superblock feature masks. These are to be used for new v5 559 * Extended v5 superblock feature masks. These are to be used for new v5
566 * superblock features only. 560 * superblock features only.
@@ -599,7 +593,9 @@ xfs_sb_has_ro_compat_feature(
599 return (sbp->sb_features_ro_compat & feature) != 0; 593 return (sbp->sb_features_ro_compat & feature) != 0;
600} 594}
601 595
596#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */
602#define XFS_SB_FEAT_INCOMPAT_ALL 0 597#define XFS_SB_FEAT_INCOMPAT_ALL 0
598
603#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL 599#define XFS_SB_FEAT_INCOMPAT_UNKNOWN ~XFS_SB_FEAT_INCOMPAT_ALL
604static inline bool 600static inline bool
605xfs_sb_has_incompat_feature( 601xfs_sb_has_incompat_feature(
@@ -619,11 +615,25 @@ xfs_sb_has_incompat_log_feature(
619 return (sbp->sb_features_log_incompat & feature) != 0; 615 return (sbp->sb_features_log_incompat & feature) != 0;
620} 616}
621 617
618/*
619 * V5 superblock specific feature checks
620 */
621static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp)
622{
623 return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
624}
625
622static inline int xfs_sb_version_has_pquotino(xfs_sb_t *sbp) 626static inline int xfs_sb_version_has_pquotino(xfs_sb_t *sbp)
623{ 627{
624 return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; 628 return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
625} 629}
626 630
631static inline int xfs_sb_version_hasftype(struct xfs_sb *sbp)
632{
633 return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
634 xfs_sb_has_incompat_feature(sbp, XFS_SB_FEAT_INCOMPAT_FTYPE);
635}
636
627/* 637/*
628 * end of superblock version macros 638 * end of superblock version macros
629 */ 639 */
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h
index ce44b182821f..82bbc34d54a3 100644
--- a/fs/xfs/xfs_types.h
+++ b/fs/xfs/xfs_types.h
@@ -140,6 +140,7 @@ typedef enum {
140struct xfs_name { 140struct xfs_name {
141 const unsigned char *name; 141 const unsigned char *name;
142 int len; 142 int len;
143 int type;
143}; 144};
144 145
145/* 146/*