Skip to content

Commit a317120

Browse files
Russell KingAl Viro
authored andcommitted
fs/adfs: dir: add generic copy functions
Directories can span multiple buffers, and we currently open-code memcpy access to these buffers, including dealing with entries that are split across multiple buffers. Such code exists in both directory format implementations. Provide common functions to allow data to be copied from/to the directory buffers as if they were a contiguous set of buffers, and use them when accessing directories. Signed-off-by: Russell King <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent acf5f0b commit a317120

File tree

4 files changed

+75
-82
lines changed

4 files changed

+75
-82
lines changed

fs/adfs/adfs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ extern const struct dentry_operations adfs_dentry_operations;
165165
extern const struct adfs_dir_ops adfs_f_dir_ops;
166166
extern const struct adfs_dir_ops adfs_fplus_dir_ops;
167167

168+
int adfs_dir_copyfrom(void *dst, struct adfs_dir *dir, unsigned int offset,
169+
size_t len);
170+
int adfs_dir_copyto(struct adfs_dir *dir, unsigned int offset, const void *src,
171+
size_t len);
168172
void adfs_dir_relse(struct adfs_dir *dir);
169173
void adfs_object_fixup(struct adfs_dir *dir, struct object_info *obj);
170174
extern int adfs_dir_update(struct super_block *sb, struct object_info *obj,

fs/adfs/dir.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,56 @@
1414
*/
1515
static DEFINE_RWLOCK(adfs_dir_lock);
1616

17+
int adfs_dir_copyfrom(void *dst, struct adfs_dir *dir, unsigned int offset,
18+
size_t len)
19+
{
20+
struct super_block *sb = dir->sb;
21+
unsigned int index, remain;
22+
23+
index = offset >> sb->s_blocksize_bits;
24+
offset &= sb->s_blocksize - 1;
25+
remain = sb->s_blocksize - offset;
26+
if (index + (remain < len) >= dir->nr_buffers)
27+
return -EINVAL;
28+
29+
if (remain < len) {
30+
memcpy(dst, dir->bhs[index]->b_data + offset, remain);
31+
dst += remain;
32+
len -= remain;
33+
index += 1;
34+
offset = 0;
35+
}
36+
37+
memcpy(dst, dir->bhs[index]->b_data + offset, len);
38+
39+
return 0;
40+
}
41+
42+
int adfs_dir_copyto(struct adfs_dir *dir, unsigned int offset, const void *src,
43+
size_t len)
44+
{
45+
struct super_block *sb = dir->sb;
46+
unsigned int index, remain;
47+
48+
index = offset >> sb->s_blocksize_bits;
49+
offset &= sb->s_blocksize - 1;
50+
remain = sb->s_blocksize - offset;
51+
if (index + (remain < len) >= dir->nr_buffers)
52+
return -EINVAL;
53+
54+
if (remain < len) {
55+
memcpy(dir->bhs[index]->b_data + offset, src, remain);
56+
src += remain;
57+
len -= remain;
58+
index += 1;
59+
offset = 0;
60+
}
61+
62+
memcpy(dir->bhs[index]->b_data + offset, src, len);
63+
64+
return 0;
65+
}
66+
1767
void adfs_dir_relse(struct adfs_dir *dir)
1868
{
1969
unsigned int i;

fs/adfs/dir_f.c

Lines changed: 9 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -224,24 +224,12 @@ adfs_obj2dir(struct adfs_direntry *de, struct object_info *obj)
224224
static int
225225
__adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
226226
{
227-
struct super_block *sb = dir->sb;
228227
struct adfs_direntry de;
229-
int thissize, buffer, offset;
230-
231-
buffer = pos >> sb->s_blocksize_bits;
232-
233-
if (buffer > dir->nr_buffers)
234-
return -EINVAL;
235-
236-
offset = pos & (sb->s_blocksize - 1);
237-
thissize = sb->s_blocksize - offset;
238-
if (thissize > 26)
239-
thissize = 26;
228+
int ret;
240229

241-
memcpy(&de, dir->bh[buffer]->b_data + offset, thissize);
242-
if (thissize != 26)
243-
memcpy(((char *)&de) + thissize, dir->bh[buffer + 1]->b_data,
244-
26 - thissize);
230+
ret = adfs_dir_copyfrom(&de, dir, pos, 26);
231+
if (ret)
232+
return ret;
245233

246234
if (!de.dirobname[0])
247235
return -ENOENT;
@@ -254,42 +242,16 @@ __adfs_dir_get(struct adfs_dir *dir, int pos, struct object_info *obj)
254242
static int
255243
__adfs_dir_put(struct adfs_dir *dir, int pos, struct object_info *obj)
256244
{
257-
struct super_block *sb = dir->sb;
258245
struct adfs_direntry de;
259-
int thissize, buffer, offset;
260-
261-
buffer = pos >> sb->s_blocksize_bits;
262-
263-
if (buffer > dir->nr_buffers)
264-
return -EINVAL;
265-
266-
offset = pos & (sb->s_blocksize - 1);
267-
thissize = sb->s_blocksize - offset;
268-
if (thissize > 26)
269-
thissize = 26;
246+
int ret;
270247

271-
/*
272-
* Get the entry in total
273-
*/
274-
memcpy(&de, dir->bh[buffer]->b_data + offset, thissize);
275-
if (thissize != 26)
276-
memcpy(((char *)&de) + thissize, dir->bh[buffer + 1]->b_data,
277-
26 - thissize);
248+
ret = adfs_dir_copyfrom(&de, dir, pos, 26);
249+
if (ret)
250+
return ret;
278251

279-
/*
280-
* update it
281-
*/
282252
adfs_obj2dir(&de, obj);
283253

284-
/*
285-
* Put the new entry back
286-
*/
287-
memcpy(dir->bh[buffer]->b_data + offset, &de, thissize);
288-
if (thissize != 26)
289-
memcpy(dir->bh[buffer + 1]->b_data, ((char *)&de) + thissize,
290-
26 - thissize);
291-
292-
return 0;
254+
return adfs_dir_copyto(dir, pos, &de, 26);
293255
}
294256

295257
/*

fs/adfs/dir_fplus.c

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -112,51 +112,26 @@ adfs_fplus_setpos(struct adfs_dir *dir, unsigned int fpos)
112112
return ret;
113113
}
114114

115-
static void
116-
dir_memcpy(struct adfs_dir *dir, unsigned int offset, void *to, int len)
117-
{
118-
struct super_block *sb = dir->sb;
119-
unsigned int buffer, partial, remainder;
120-
121-
buffer = offset >> sb->s_blocksize_bits;
122-
offset &= sb->s_blocksize - 1;
123-
124-
partial = sb->s_blocksize - offset;
125-
126-
if (partial >= len)
127-
memcpy(to, dir->bhs[buffer]->b_data + offset, len);
128-
else {
129-
char *c = (char *)to;
130-
131-
remainder = len - partial;
132-
133-
memcpy(c,
134-
dir->bhs[buffer]->b_data + offset,
135-
partial);
136-
137-
memcpy(c + partial,
138-
dir->bhs[buffer + 1]->b_data,
139-
remainder);
140-
}
141-
}
142-
143115
static int
144116
adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj)
145117
{
146118
struct adfs_bigdirheader *h =
147119
(struct adfs_bigdirheader *) dir->bhs[0]->b_data;
148120
struct adfs_bigdirentry bde;
149121
unsigned int offset;
150-
int ret = -ENOENT;
122+
int ret;
151123

152124
if (dir->pos >= le32_to_cpu(h->bigdirentries))
153-
goto out;
125+
return -ENOENT;
154126

155127
offset = offsetof(struct adfs_bigdirheader, bigdirname);
156128
offset += ((le32_to_cpu(h->bigdirnamelen) + 4) & ~3);
157129
offset += dir->pos * sizeof(struct adfs_bigdirentry);
158130

159-
dir_memcpy(dir, offset, &bde, sizeof(struct adfs_bigdirentry));
131+
ret = adfs_dir_copyfrom(&bde, dir, offset,
132+
sizeof(struct adfs_bigdirentry));
133+
if (ret)
134+
return ret;
160135

161136
obj->loadaddr = le32_to_cpu(bde.bigdirload);
162137
obj->execaddr = le32_to_cpu(bde.bigdirexec);
@@ -170,13 +145,15 @@ adfs_fplus_getnext(struct adfs_dir *dir, struct object_info *obj)
170145
offset += le32_to_cpu(h->bigdirentries) * sizeof(struct adfs_bigdirentry);
171146
offset += le32_to_cpu(bde.bigdirobnameptr);
172147

173-
dir_memcpy(dir, offset, obj->name, obj->name_len);
148+
ret = adfs_dir_copyfrom(obj->name, dir, offset, obj->name_len);
149+
if (ret)
150+
return ret;
151+
174152
adfs_object_fixup(dir, obj);
175153

176154
dir->pos += 1;
177-
ret = 0;
178-
out:
179-
return ret;
155+
156+
return 0;
180157
}
181158

182159
const struct adfs_dir_ops adfs_fplus_dir_ops = {

0 commit comments

Comments
 (0)