diff options
-rw-r--r-- | fs/xfs/xfs_da_btree.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.c | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.h | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_block.c | 16 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_data.c | 13 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_format.h | 183 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_leaf.c | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_priv.h | 9 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_readdir.c | 69 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_sf.c | 121 | ||||
-rw-r--r-- | fs/xfs/xfs_iops.c | 27 | ||||
-rw-r--r-- | fs/xfs/xfs_sb.h | 22 | ||||
-rw-r--r-- | fs/xfs/xfs_types.h | 1 |
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 { | |||
176 | typedef struct xfs_da_args { | 176 | typedef 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 | ||
40 | struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2}; | 40 | struct 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); | |||
68 | extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp); | 68 | extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp); |
69 | extern void xfs_dir2_sf_put_parent_ino(struct xfs_dir2_sf_hdr *sfp, | 69 | extern void xfs_dir2_sf_put_parent_ino(struct xfs_dir2_sf_hdr *sfp, |
70 | xfs_ino_t ino); | 70 | xfs_ino_t ino); |
71 | extern xfs_ino_t xfs_dir2_sfe_get_ino(struct xfs_dir2_sf_hdr *sfp, | 71 | extern 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); |
73 | extern void xfs_dir2_sfe_put_ino( struct xfs_dir2_sf_hdr *, | 73 | extern 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 | */ |
74 | typedef __uint16_t xfs_dir2_data_off_t; | 91 | typedef __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 | ||
165 | static inline int | ||
166 | xfs_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 | |||
175 | static inline struct xfs_dir2_sf_entry * | 185 | static inline struct xfs_dir2_sf_entry * |
176 | xfs_dir2_sf_firstentry(struct xfs_dir2_sf_hdr *hdr) | 186 | xfs_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 | ||
192 | static inline int | ||
193 | xfs_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 | |||
182 | static inline struct xfs_dir2_sf_entry * | 208 | static inline struct xfs_dir2_sf_entry * |
183 | xfs_dir2_sf_nextentry(struct xfs_dir2_sf_hdr *hdr, | 209 | xfs_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 | */ | ||
223 | static inline __uint8_t * | ||
224 | xfs_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 | |||
231 | static inline __uint8_t | ||
232 | xfs_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 | |||
248 | static inline void | ||
249 | xfs_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 | */ |
291 | typedef struct xfs_dir2_data_entry { | 370 | typedef 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 | */ |
314 | static inline int xfs_dir2_data_entsize(int n) | 394 | static 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 | } | ||
407 | static inline int | ||
408 | xfs_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 | |||
416 | static inline __uint8_t | ||
417 | xfs_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 | |||
432 | static inline void | ||
433 | xfs_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 | */ |
323 | static inline __be16 * | 448 | static inline __be16 * |
324 | xfs_dir2_data_entry_tag_p(struct xfs_dir2_data_entry *dep) | 449 | xfs_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 | ||
386 | static inline xfs_dir2_data_aoff_t | 517 | static inline xfs_dir2_data_aoff_t |
387 | xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr) | 518 | xfs_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) | |||
392 | static inline xfs_dir2_data_aoff_t | 523 | static inline xfs_dir2_data_aoff_t |
393 | xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr) | 524 | xfs_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 | ||
398 | static inline xfs_dir2_data_aoff_t | 532 | static inline xfs_dir2_data_aoff_t |
399 | xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr) | 533 | xfs_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 | ||
21 | struct dir_context; | ||
22 | |||
21 | /* xfs_dir2.c */ | 23 | /* xfs_dir2.c */ |
22 | extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); | 24 | extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); |
23 | extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, | 25 | extern 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, | |||
25 | extern int xfs_dir_cilookup_result(struct xfs_da_args *args, | 27 | extern 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 | ||
31 | extern const unsigned char xfs_mode_to_ftype[]; | ||
32 | |||
33 | extern 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 */ |
29 | extern int xfs_dir3_block_read(struct xfs_trans *tp, struct xfs_inode *dp, | 38 | extern 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 | */ | ||
42 | static 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 | |||
47 | unsigned char | ||
48 | xfs_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 | */ | ||
66 | const 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 | |||
39 | STATIC int | 77 | STATIC int |
40 | xfs_dir2_sf_getdents( | 78 | xfs_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 | */ |
111 | static xfs_dir2_inou_t * | 112 | static xfs_dir2_inou_t * |
112 | xfs_dir2_sfe_inop( | 113 | xfs_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 | ||
118 | xfs_ino_t | 123 | xfs_ino_t |
119 | xfs_dir2_sfe_get_ino( | 124 | xfs_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 | ||
126 | void | 132 | void |
127 | xfs_dir2_sfe_put_ino( | 133 | xfs_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( | |||
88 | static void | 91 | static void |
89 | xfs_dentry_to_name( | 92 | xfs_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 | ||
97 | STATIC void | 102 | STATIC 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 | ||
558 | static 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 |
604 | static inline bool | 600 | static inline bool |
605 | xfs_sb_has_incompat_feature( | 601 | xfs_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 | */ | ||
621 | static inline int xfs_sb_version_hascrc(xfs_sb_t *sbp) | ||
622 | { | ||
623 | return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5; | ||
624 | } | ||
625 | |||
622 | static inline int xfs_sb_version_has_pquotino(xfs_sb_t *sbp) | 626 | static 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 | ||
631 | static 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 { | |||
140 | struct xfs_name { | 140 | struct 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 | /* |