2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
7 * of the GNU General Public License v.2.
10 #include <linux/sched.h>
11 #include <linux/slab.h>
12 #include <linux/spinlock.h>
13 #include <linux/completion.h>
14 #include <linux/buffer_head.h>
15 #include <asm/semaphore.h>
16 #include <asm/uaccess.h>
25 int gfs2_jdata_get_buffer(struct gfs2_inode
*ip
, uint64_t block
, int new,
26 struct buffer_head
**bhp
)
28 struct buffer_head
*bh
;
32 bh
= gfs2_meta_new(ip
->i_gl
, block
);
33 gfs2_trans_add_bh(ip
->i_gl
, bh
, 1);
34 gfs2_metatype_set(bh
, GFS2_METATYPE_JD
, GFS2_FORMAT_JD
);
35 gfs2_buffer_clear_tail(bh
, sizeof(struct gfs2_meta_header
));
37 error
= gfs2_meta_read(ip
->i_gl
, block
,
38 DIO_START
| DIO_WAIT
, &bh
);
41 if (gfs2_metatype_check(ip
->i_sbd
, bh
, GFS2_METATYPE_JD
)) {
53 * gfs2_copy2mem - Trivial copy function for gfs2_jdata_read()
54 * @bh: The buffer to copy from, or NULL meaning zero the buffer
55 * @buf: The buffer to copy/zero
56 * @offset: The offset in the buffer to copy from
57 * @size: The amount of data to copy/zero
62 int gfs2_copy2mem(struct buffer_head
*bh
, char **buf
, unsigned int offset
,
66 memcpy(*buf
, bh
->b_data
+ offset
, size
);
68 memset(*buf
, 0, size
);
74 * gfs2_copy2user - Copy bytes to user space for gfs2_jdata_read()
76 * @buf: The destination of the data
77 * @offset: The offset into the buffer
78 * @size: The amount of data to copy
83 int gfs2_copy2user(struct buffer_head
*bh
, char **buf
, unsigned int offset
,
89 error
= copy_to_user(*buf
, bh
->b_data
+ offset
, size
);
91 error
= clear_user(*buf
, size
);
101 static int jdata_read_stuffed(struct gfs2_inode
*ip
, char *buf
,
102 unsigned int offset
, unsigned int size
,
103 read_copy_fn_t copy_fn
)
105 struct buffer_head
*dibh
;
108 error
= gfs2_meta_inode_buffer(ip
, &dibh
);
110 error
= copy_fn(dibh
, &buf
,
111 offset
+ sizeof(struct gfs2_dinode
), size
);
115 return (error
) ? error
: size
;
119 * gfs2_jdata_read - Read a jdata file
120 * @ip: The GFS2 Inode
121 * @buf: The buffer to place result into
122 * @offset: File offset to begin jdata_readng from
123 * @size: Amount of data to transfer
124 * @copy_fn: Function to actually perform the copy
126 * The @copy_fn only copies a maximum of a single block at once so
127 * we are safe calling it with int arguments. It is done so that
128 * we don't needlessly put 64bit arguments on the stack and it
129 * also makes the code in the @copy_fn nicer too.
131 * Returns: The amount of data actually copied or the error
134 int gfs2_jdata_read(struct gfs2_inode
*ip
, char __user
*buf
, uint64_t offset
,
135 unsigned int size
, read_copy_fn_t copy_fn
)
137 struct gfs2_sbd
*sdp
= ip
->i_sbd
;
138 uint64_t lblock
, dblock
;
144 if (offset
>= ip
->i_di
.di_size
)
147 if ((offset
+ size
) > ip
->i_di
.di_size
)
148 size
= ip
->i_di
.di_size
- offset
;
153 if (gfs2_is_stuffed(ip
))
154 return jdata_read_stuffed(ip
, buf
, (unsigned int)offset
, size
,
157 if (gfs2_assert_warn(sdp
, gfs2_is_jdata(ip
)))
161 o
= do_div(lblock
, sdp
->sd_jbsize
) +
162 sizeof(struct gfs2_meta_header
);
164 while (copied
< size
) {
166 struct buffer_head
*bh
;
169 amount
= size
- copied
;
170 if (amount
> sdp
->sd_sb
.sb_bsize
- o
)
171 amount
= sdp
->sd_sb
.sb_bsize
- o
;
175 error
= gfs2_block_map(ip
, lblock
, &new,
182 gfs2_meta_ra(ip
->i_gl
, dblock
, extlen
);
185 error
= gfs2_jdata_get_buffer(ip
, dblock
, new, &bh
);
193 error
= copy_fn(bh
, &buf
, o
, amount
);
201 o
= sizeof(struct gfs2_meta_header
);
207 return (copied
) ? copied
: error
;
211 * gfs2_copy_from_mem - Trivial copy function for gfs2_jdata_write()
212 * @bh: The buffer to copy to or clear
213 * @buf: The buffer to copy from
214 * @offset: The offset in the buffer to write to
215 * @size: The amount of data to write
220 int gfs2_copy_from_mem(struct gfs2_inode
*ip
, struct buffer_head
*bh
,
221 const char **buf
, unsigned int offset
, unsigned int size
)
223 gfs2_trans_add_bh(ip
->i_gl
, bh
, 1);
224 memcpy(bh
->b_data
+ offset
, *buf
, size
);
232 * gfs2_copy_from_user - Copy bytes from user space for gfs2_jdata_write()
233 * @bh: The buffer to copy to or clear
234 * @buf: The buffer to copy from
235 * @offset: The offset in the buffer to write to
236 * @size: The amount of data to write
241 int gfs2_copy_from_user(struct gfs2_inode
*ip
, struct buffer_head
*bh
,
242 const char __user
**buf
, unsigned int offset
, unsigned int size
)
246 gfs2_trans_add_bh(ip
->i_gl
, bh
, 1);
247 if (copy_from_user(bh
->b_data
+ offset
, *buf
, size
))
255 static int jdata_write_stuffed(struct gfs2_inode
*ip
, char *buf
,
256 unsigned int offset
, unsigned int size
,
257 write_copy_fn_t copy_fn
)
259 struct buffer_head
*dibh
;
262 error
= gfs2_meta_inode_buffer(ip
, &dibh
);
268 offset
+ sizeof(struct gfs2_dinode
), size
);
270 if (ip
->i_di
.di_size
< offset
+ size
)
271 ip
->i_di
.di_size
= offset
+ size
;
272 ip
->i_di
.di_mtime
= ip
->i_di
.di_ctime
= get_seconds();
273 gfs2_dinode_out(&ip
->i_di
, dibh
->b_data
);
278 return (error
) ? error
: size
;
282 * gfs2_jdata_write - Write bytes to a file
283 * @ip: The GFS2 inode
284 * @buf: The buffer containing information to be written
285 * @offset: The file offset to start writing at
286 * @size: The amount of data to write
287 * @copy_fn: Function to do the actual copying
289 * Returns: The number of bytes correctly written or error code
292 int gfs2_jdata_write(struct gfs2_inode
*ip
, const char __user
*buf
, uint64_t offset
,
293 unsigned int size
, write_copy_fn_t copy_fn
)
295 struct gfs2_sbd
*sdp
= ip
->i_sbd
;
296 struct buffer_head
*dibh
;
297 uint64_t lblock
, dblock
;
306 if (gfs2_is_stuffed(ip
) &&
307 offset
+ size
<= sdp
->sd_sb
.sb_bsize
- sizeof(struct gfs2_dinode
))
308 return jdata_write_stuffed(ip
, buf
, (unsigned int)offset
, size
,
311 if (gfs2_assert_warn(sdp
, gfs2_is_jdata(ip
)))
314 if (gfs2_is_stuffed(ip
)) {
315 error
= gfs2_unstuff_dinode(ip
, NULL
, NULL
);
321 o
= do_div(lblock
, sdp
->sd_jbsize
) + sizeof(struct gfs2_meta_header
);
323 while (copied
< size
) {
325 struct buffer_head
*bh
;
328 amount
= size
- copied
;
329 if (amount
> sdp
->sd_sb
.sb_bsize
- o
)
330 amount
= sdp
->sd_sb
.sb_bsize
- o
;
334 error
= gfs2_block_map(ip
, lblock
, &new,
339 if (gfs2_assert_withdraw(sdp
, dblock
))
343 error
= gfs2_jdata_get_buffer(ip
, dblock
,
344 (amount
== sdp
->sd_jbsize
) ? 1 : new,
349 error
= copy_fn(ip
, bh
, &buf
, o
, amount
);
359 o
= sizeof(struct gfs2_meta_header
);
363 error
= gfs2_meta_inode_buffer(ip
, &dibh
);
367 if (ip
->i_di
.di_size
< offset
+ copied
)
368 ip
->i_di
.di_size
= offset
+ copied
;
369 ip
->i_di
.di_mtime
= ip
->i_di
.di_ctime
= get_seconds();
371 gfs2_trans_add_bh(ip
->i_gl
, dibh
, 1);
372 gfs2_dinode_out(&ip
->i_di
, dibh
->b_data
);
This page took 0.038173 seconds and 5 git commands to generate.