blob: 62f55a0186ae6fbc7b7142203e51f0b3f8047e38 [file] [log] [blame]
Dave Chinner32c54832013-10-29 22:11:46 +11001/*
2 * Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
3 * Copyright (c) 2013 Red Hat, Inc.
4 * All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19#include "xfs.h"
20#include "xfs_fs.h"
21#include "xfs_format.h"
22#include "xfs_log_format.h"
23#include "xfs_trans_resv.h"
24#include "xfs_sb.h"
25#include "xfs_ag.h"
26#include "xfs_mount.h"
27#include "xfs_da_format.h"
28#include "xfs_inode.h"
29#include "xfs_dir2.h"
30
31
32static int
33xfs_dir2_sf_entsize(
34 struct xfs_dir2_sf_hdr *hdr,
35 int len)
36{
37 int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */
38
39 count += len; /* name */
40 count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) :
41 sizeof(xfs_dir2_ino4_t); /* ino # */
42 return count;
43}
44
45static int
46xfs_dir3_sf_entsize(
47 struct xfs_dir2_sf_hdr *hdr,
48 int len)
49{
50 return xfs_dir2_sf_entsize(hdr, len) + sizeof(__uint8_t);
51}
52
53static struct xfs_dir2_sf_entry *
54xfs_dir2_sf_nextentry(
55 struct xfs_dir2_sf_hdr *hdr,
56 struct xfs_dir2_sf_entry *sfep)
57{
58 return (struct xfs_dir2_sf_entry *)
59 ((char *)sfep + xfs_dir2_sf_entsize(hdr, sfep->namelen));
60}
61
62static struct xfs_dir2_sf_entry *
63xfs_dir3_sf_nextentry(
64 struct xfs_dir2_sf_hdr *hdr,
65 struct xfs_dir2_sf_entry *sfep)
66{
67 return (struct xfs_dir2_sf_entry *)
68 ((char *)sfep + xfs_dir3_sf_entsize(hdr, sfep->namelen));
69}
70
71
Dave Chinner47401752013-10-29 22:11:47 +110072/*
73 * For filetype enabled shortform directories, the file type field is stored at
74 * the end of the name. Because it's only a single byte, endian conversion is
75 * not necessary. For non-filetype enable directories, the type is always
76 * unknown and we never store the value.
77 */
78static __uint8_t
79xfs_dir2_sfe_get_ftype(
80 struct xfs_dir2_sf_entry *sfep)
81{
82 return XFS_DIR3_FT_UNKNOWN;
83}
84
85static void
86xfs_dir2_sfe_put_ftype(
87 struct xfs_dir2_sf_entry *sfep,
88 __uint8_t ftype)
89{
90 ASSERT(ftype < XFS_DIR3_FT_MAX);
91}
92
93static __uint8_t
94xfs_dir3_sfe_get_ftype(
95 struct xfs_dir2_sf_entry *sfep)
96{
97 __uint8_t ftype;
98
99 ftype = sfep->name[sfep->namelen];
100 if (ftype >= XFS_DIR3_FT_MAX)
101 return XFS_DIR3_FT_UNKNOWN;
102 return ftype;
103}
104
105static void
106xfs_dir3_sfe_put_ftype(
107 struct xfs_dir2_sf_entry *sfep,
108 __uint8_t ftype)
109{
110 ASSERT(ftype < XFS_DIR3_FT_MAX);
111
112 sfep->name[sfep->namelen] = ftype;
113}
114
115/*
116 * Inode numbers in short-form directories can come in two versions,
117 * either 4 bytes or 8 bytes wide. These helpers deal with the
118 * two forms transparently by looking at the headers i8count field.
119 *
120 * For 64-bit inode number the most significant byte must be zero.
121 */
122static xfs_ino_t
123xfs_dir2_sf_get_ino(
124 struct xfs_dir2_sf_hdr *hdr,
125 xfs_dir2_inou_t *from)
126{
127 if (hdr->i8count)
128 return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL;
129 else
130 return get_unaligned_be32(&from->i4.i);
131}
132
133static void
134xfs_dir2_sf_put_ino(
135 struct xfs_dir2_sf_hdr *hdr,
136 xfs_dir2_inou_t *to,
137 xfs_ino_t ino)
138{
139 ASSERT((ino & 0xff00000000000000ULL) == 0);
140
141 if (hdr->i8count)
142 put_unaligned_be64(ino, &to->i8.i);
143 else
144 put_unaligned_be32(ino, &to->i4.i);
145}
146
147static xfs_ino_t
148xfs_dir2_sf_get_parent_ino(
149 struct xfs_dir2_sf_hdr *hdr)
150{
151 return xfs_dir2_sf_get_ino(hdr, &hdr->parent);
152}
153
154static void
155xfs_dir2_sf_put_parent_ino(
156 struct xfs_dir2_sf_hdr *hdr,
157 xfs_ino_t ino)
158{
159 xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino);
160}
161
162/*
163 * In short-form directory entries the inode numbers are stored at variable
164 * offset behind the entry name. If the entry stores a filetype value, then it
165 * sits between the name and the inode number. Hence the inode numbers may only
166 * be accessed through the helpers below.
167 */
168static xfs_ino_t
169xfs_dir2_sfe_get_ino(
170 struct xfs_dir2_sf_hdr *hdr,
171 struct xfs_dir2_sf_entry *sfep)
172{
173 return xfs_dir2_sf_get_ino(hdr,
174 (xfs_dir2_inou_t *)&sfep->name[sfep->namelen]);
175}
176
177static void
178xfs_dir2_sfe_put_ino(
179 struct xfs_dir2_sf_hdr *hdr,
180 struct xfs_dir2_sf_entry *sfep,
181 xfs_ino_t ino)
182{
183 xfs_dir2_sf_put_ino(hdr,
184 (xfs_dir2_inou_t *)&sfep->name[sfep->namelen], ino);
185}
186
187static xfs_ino_t
188xfs_dir3_sfe_get_ino(
189 struct xfs_dir2_sf_hdr *hdr,
190 struct xfs_dir2_sf_entry *sfep)
191{
192 return xfs_dir2_sf_get_ino(hdr,
193 (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1]);
194}
195
196static void
197xfs_dir3_sfe_put_ino(
198 struct xfs_dir2_sf_hdr *hdr,
199 struct xfs_dir2_sf_entry *sfep,
200 xfs_ino_t ino)
201{
202 xfs_dir2_sf_put_ino(hdr,
203 (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1], ino);
204}
205
Dave Chinner32c54832013-10-29 22:11:46 +1100206const struct xfs_dir_ops xfs_dir2_ops = {
207 .sf_entsize = xfs_dir2_sf_entsize,
208 .sf_nextentry = xfs_dir2_sf_nextentry,
Dave Chinner47401752013-10-29 22:11:47 +1100209 .sf_get_ftype = xfs_dir2_sfe_get_ftype,
210 .sf_put_ftype = xfs_dir2_sfe_put_ftype,
211 .sf_get_ino = xfs_dir2_sfe_get_ino,
212 .sf_put_ino = xfs_dir2_sfe_put_ino,
213 .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
214 .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
Dave Chinner32c54832013-10-29 22:11:46 +1100215};
216
217const struct xfs_dir_ops xfs_dir2_ftype_ops = {
218 .sf_entsize = xfs_dir3_sf_entsize,
219 .sf_nextentry = xfs_dir3_sf_nextentry,
Dave Chinner47401752013-10-29 22:11:47 +1100220 .sf_get_ftype = xfs_dir3_sfe_get_ftype,
221 .sf_put_ftype = xfs_dir3_sfe_put_ftype,
222 .sf_get_ino = xfs_dir3_sfe_get_ino,
223 .sf_put_ino = xfs_dir3_sfe_put_ino,
224 .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
225 .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
Dave Chinner32c54832013-10-29 22:11:46 +1100226};
227
228const struct xfs_dir_ops xfs_dir3_ops = {
229 .sf_entsize = xfs_dir3_sf_entsize,
230 .sf_nextentry = xfs_dir3_sf_nextentry,
Dave Chinner47401752013-10-29 22:11:47 +1100231 .sf_get_ftype = xfs_dir3_sfe_get_ftype,
232 .sf_put_ftype = xfs_dir3_sfe_put_ftype,
233 .sf_get_ino = xfs_dir3_sfe_get_ino,
234 .sf_put_ino = xfs_dir3_sfe_put_ino,
235 .sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
236 .sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,
Dave Chinner32c54832013-10-29 22:11:46 +1100237};