Blame view
fs/gfs2/file.c
25.5 KB
b3b94faa5 [GFS2] The core o... |
1 2 |
/* * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3a8a9a103 [GFS2] Update cop... |
3 |
* Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. |
b3b94faa5 [GFS2] The core o... |
4 5 6 |
* * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions |
e9fc2aa09 [GFS2] Update cop... |
7 |
* of the GNU General Public License version 2. |
b3b94faa5 [GFS2] The core o... |
8 |
*/ |
b3b94faa5 [GFS2] The core o... |
9 10 11 12 13 14 15 16 |
#include <linux/slab.h> #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/buffer_head.h> #include <linux/pagemap.h> #include <linux/uio.h> #include <linux/blkdev.h> #include <linux/mm.h> |
f58ba8891 [GFS2] don't call... |
17 |
#include <linux/mount.h> |
18ec7d5c3 [GFS2] Make journ... |
18 |
#include <linux/fs.h> |
5c676f6d3 [GFS2] Macros rem... |
19 |
#include <linux/gfs2_ondisk.h> |
71b86f562 [GFS2] Further up... |
20 |
#include <linux/ext2_fs.h> |
2fe17c107 fallocate should ... |
21 22 |
#include <linux/falloc.h> #include <linux/swap.h> |
71b86f562 [GFS2] Further up... |
23 |
#include <linux/crc32.h> |
33c3de328 [GFS2] Don't flus... |
24 |
#include <linux/writeback.h> |
b3b94faa5 [GFS2] The core o... |
25 |
#include <asm/uaccess.h> |
f057f6cdf GFS2: Merge lock_... |
26 27 |
#include <linux/dlm.h> #include <linux/dlm_plock.h> |
b3b94faa5 [GFS2] The core o... |
28 29 |
#include "gfs2.h" |
5c676f6d3 [GFS2] Macros rem... |
30 |
#include "incore.h" |
b3b94faa5 [GFS2] The core o... |
31 32 33 34 35 |
#include "bmap.h" #include "dir.h" #include "glock.h" #include "glops.h" #include "inode.h" |
b3b94faa5 [GFS2] The core o... |
36 37 |
#include "log.h" #include "meta_io.h" |
b3b94faa5 [GFS2] The core o... |
38 39 40 |
#include "quota.h" #include "rgrp.h" #include "trans.h" |
5c676f6d3 [GFS2] Macros rem... |
41 |
#include "util.h" |
b3b94faa5 [GFS2] The core o... |
42 |
|
b3b94faa5 [GFS2] The core o... |
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
/** * gfs2_llseek - seek to a location in a file * @file: the file * @offset: the offset * @origin: Where to seek from (SEEK_SET, SEEK_CUR, or SEEK_END) * * SEEK_END requires the glock for the file because it references the * file's size. * * Returns: The new offset, or errno */ static loff_t gfs2_llseek(struct file *file, loff_t offset, int origin) { |
feaa7bba0 [GFS2] Fix unlink... |
57 |
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); |
b3b94faa5 [GFS2] The core o... |
58 59 |
struct gfs2_holder i_gh; loff_t error; |
9453615a1 GFS2: Fix lseek a... |
60 61 62 63 |
switch (origin) { case SEEK_END: /* These reference inode->i_size */ case SEEK_DATA: case SEEK_HOLE: |
b3b94faa5 [GFS2] The core o... |
64 65 66 |
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); if (!error) { |
ef3d0fd27 vfs: do (nearly) ... |
67 |
error = generic_file_llseek(file, offset, origin); |
b3b94faa5 [GFS2] The core o... |
68 69 |
gfs2_glock_dq_uninit(&i_gh); } |
9453615a1 GFS2: Fix lseek a... |
70 71 72 |
break; case SEEK_CUR: case SEEK_SET: |
ef3d0fd27 vfs: do (nearly) ... |
73 |
error = generic_file_llseek(file, offset, origin); |
9453615a1 GFS2: Fix lseek a... |
74 75 76 77 |
break; default: error = -EINVAL; } |
b3b94faa5 [GFS2] The core o... |
78 79 80 |
return error; } |
b3b94faa5 [GFS2] The core o... |
81 |
/** |
f0e522a90 [GFS2] Remove "NF... |
82 |
* gfs2_readdir - Read directory entries from a directory |
b3b94faa5 [GFS2] The core o... |
83 84 85 86 87 88 |
* @file: The directory to read from * @dirent: Buffer for dirents * @filldir: Function used to do the copying * * Returns: errno */ |
f0e522a90 [GFS2] Remove "NF... |
89 |
static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) |
b3b94faa5 [GFS2] The core o... |
90 |
{ |
71b86f562 [GFS2] Further up... |
91 |
struct inode *dir = file->f_mapping->host; |
feaa7bba0 [GFS2] Fix unlink... |
92 |
struct gfs2_inode *dip = GFS2_I(dir); |
b3b94faa5 [GFS2] The core o... |
93 |
struct gfs2_holder d_gh; |
cd915493f [GFS2] Change all... |
94 |
u64 offset = file->f_pos; |
b3b94faa5 [GFS2] The core o... |
95 |
int error; |
719ee3446 GFS2: high time t... |
96 97 |
gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); error = gfs2_glock_nq(&d_gh); |
b3b94faa5 [GFS2] The core o... |
98 99 100 101 |
if (error) { gfs2_holder_uninit(&d_gh); return error; } |
dfe4d34b3 GFS2: Add readahe... |
102 |
error = gfs2_dir_read(dir, &offset, dirent, filldir, &file->f_ra); |
b3b94faa5 [GFS2] The core o... |
103 104 |
gfs2_glock_dq_uninit(&d_gh); |
b3b94faa5 [GFS2] The core o... |
105 |
file->f_pos = offset; |
b3b94faa5 [GFS2] The core o... |
106 107 |
return error; } |
128e5ebaf [GFS2] Remove ifl... |
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
/** * fsflags_cvt * @table: A table of 32 u32 flags * @val: a 32 bit value to convert * * This function can be used to convert between fsflags values and * GFS2's own flags values. * * Returns: the converted flags */ static u32 fsflags_cvt(const u32 *table, u32 val) { u32 res = 0; while(val) { if (val & 1) res |= *table; table++; val >>= 1; } return res; } |
b3b94faa5 [GFS2] The core o... |
129 |
|
128e5ebaf [GFS2] Remove ifl... |
130 131 132 133 134 135 |
static const u32 fsflags_to_gfs2[32] = { [3] = GFS2_DIF_SYNC, [4] = GFS2_DIF_IMMUTABLE, [5] = GFS2_DIF_APPENDONLY, [7] = GFS2_DIF_NOATIME, [12] = GFS2_DIF_EXHASH, |
b9af7ca6d [GFS2] Fix settin... |
136 |
[14] = GFS2_DIF_INHERIT_JDATA, |
71b86f562 [GFS2] Further up... |
137 |
}; |
128e5ebaf [GFS2] Remove ifl... |
138 139 140 141 142 143 |
static const u32 gfs2_to_fsflags[32] = { [gfs2fl_Sync] = FS_SYNC_FL, [gfs2fl_Immutable] = FS_IMMUTABLE_FL, [gfs2fl_AppendOnly] = FS_APPEND_FL, [gfs2fl_NoAtime] = FS_NOATIME_FL, [gfs2fl_ExHash] = FS_INDEX_FL, |
128e5ebaf [GFS2] Remove ifl... |
144 |
[gfs2fl_InheritJdata] = FS_JOURNAL_DATA_FL, |
7ea9ea832 [GFS2] Update ioc... |
145 |
}; |
71b86f562 [GFS2] Further up... |
146 |
|
b09e593d7 [GFS2] Fix a ref ... |
147 |
static int gfs2_get_flags(struct file *filp, u32 __user *ptr) |
71b86f562 [GFS2] Further up... |
148 |
{ |
81454098f [PATCH] struct pa... |
149 |
struct inode *inode = filp->f_path.dentry->d_inode; |
feaa7bba0 [GFS2] Fix unlink... |
150 |
struct gfs2_inode *ip = GFS2_I(inode); |
71b86f562 [GFS2] Further up... |
151 152 |
struct gfs2_holder gh; int error; |
128e5ebaf [GFS2] Remove ifl... |
153 |
u32 fsflags; |
71b86f562 [GFS2] Further up... |
154 |
|
719ee3446 GFS2: high time t... |
155 156 |
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); error = gfs2_glock_nq(&gh); |
71b86f562 [GFS2] Further up... |
157 158 |
if (error) return error; |
907b9bceb [GFS2/DLM] Fix tr... |
159 |
|
383f01fbf GFS2: Banish stru... |
160 161 |
fsflags = fsflags_cvt(gfs2_to_fsflags, ip->i_diskflags); if (!S_ISDIR(inode->i_mode) && ip->i_diskflags & GFS2_DIF_JDATA) |
c9f6a6bbc [GFS2] Remove sup... |
162 |
fsflags |= FS_JOURNAL_DATA_FL; |
128e5ebaf [GFS2] Remove ifl... |
163 |
if (put_user(fsflags, ptr)) |
71b86f562 [GFS2] Further up... |
164 |
error = -EFAULT; |
3cc3f710c [GFS2] Use ->page... |
165 |
gfs2_glock_dq(&gh); |
71b86f562 [GFS2] Further up... |
166 167 168 |
gfs2_holder_uninit(&gh); return error; } |
6b124d8db [GFS2] Only set i... |
169 170 171 |
void gfs2_set_inode_flags(struct inode *inode) { struct gfs2_inode *ip = GFS2_I(inode); |
6b124d8db [GFS2] Only set i... |
172 |
unsigned int flags = inode->i_flags; |
9964afbb7 GFS2: Add S_NOSEC... |
173 174 175 |
flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC|S_NOSEC); if ((ip->i_eattr == 0) && !is_sxid(inode->i_mode)) inode->i_flags |= S_NOSEC; |
383f01fbf GFS2: Banish stru... |
176 |
if (ip->i_diskflags & GFS2_DIF_IMMUTABLE) |
6b124d8db [GFS2] Only set i... |
177 |
flags |= S_IMMUTABLE; |
383f01fbf GFS2: Banish stru... |
178 |
if (ip->i_diskflags & GFS2_DIF_APPENDONLY) |
6b124d8db [GFS2] Only set i... |
179 |
flags |= S_APPEND; |
383f01fbf GFS2: Banish stru... |
180 |
if (ip->i_diskflags & GFS2_DIF_NOATIME) |
6b124d8db [GFS2] Only set i... |
181 |
flags |= S_NOATIME; |
383f01fbf GFS2: Banish stru... |
182 |
if (ip->i_diskflags & GFS2_DIF_SYNC) |
6b124d8db [GFS2] Only set i... |
183 184 185 |
flags |= S_SYNC; inode->i_flags = flags; } |
71b86f562 [GFS2] Further up... |
186 187 |
/* Flags that can be set by user space */ #define GFS2_FLAGS_USER_SET (GFS2_DIF_JDATA| \ |
71b86f562 [GFS2] Further up... |
188 189 190 191 192 |
GFS2_DIF_IMMUTABLE| \ GFS2_DIF_APPENDONLY| \ GFS2_DIF_NOATIME| \ GFS2_DIF_SYNC| \ GFS2_DIF_SYSTEM| \ |
71b86f562 [GFS2] Further up... |
193 194 195 196 197 198 199 200 201 |
GFS2_DIF_INHERIT_JDATA) /** * gfs2_set_flags - set flags on an inode * @inode: The inode * @flags: The flags to set * @mask: Indicates which flags are valid * */ |
b09e593d7 [GFS2] Fix a ref ... |
202 |
static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask) |
71b86f562 [GFS2] Further up... |
203 |
{ |
81454098f [PATCH] struct pa... |
204 |
struct inode *inode = filp->f_path.dentry->d_inode; |
feaa7bba0 [GFS2] Fix unlink... |
205 206 |
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); |
71b86f562 [GFS2] Further up... |
207 208 209 |
struct buffer_head *bh; struct gfs2_holder gh; int error; |
55eccc6d0 [GFS2] Finish off... |
210 |
u32 new_flags, flags; |
71b86f562 [GFS2] Further up... |
211 |
|
a561be710 switch a bunch of... |
212 |
error = mnt_want_write_file(filp); |
52f341cf7 [GFS2] gfs2_set_f... |
213 |
if (error) |
71b86f562 [GFS2] Further up... |
214 |
return error; |
f58ba8891 [GFS2] don't call... |
215 216 217 |
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); if (error) goto out_drop_write; |
7df0e0397 GFS2: Fix permiss... |
218 |
error = -EACCES; |
2e1496707 userns: rename is... |
219 |
if (!inode_owner_or_capable(inode)) |
7df0e0397 GFS2: Fix permiss... |
220 221 222 |
goto out; error = 0; |
383f01fbf GFS2: Banish stru... |
223 |
flags = ip->i_diskflags; |
55eccc6d0 [GFS2] Finish off... |
224 |
new_flags = (flags & ~mask) | (reqflags & mask); |
71b86f562 [GFS2] Further up... |
225 226 227 228 229 230 |
if ((new_flags ^ flags) == 0) goto out; error = -EINVAL; if ((new_flags ^ flags) & ~GFS2_FLAGS_USER_SET) goto out; |
71b86f562 [GFS2] Further up... |
231 232 233 234 235 |
error = -EPERM; if (IS_IMMUTABLE(inode) && (new_flags & GFS2_DIF_IMMUTABLE)) goto out; if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY)) goto out; |
907b9bceb [GFS2/DLM] Fix tr... |
236 |
if (((new_flags ^ flags) & GFS2_DIF_IMMUTABLE) && |
b9cb98131 [GFS2] Fix attrib... |
237 |
!capable(CAP_LINUX_IMMUTABLE)) |
71b86f562 [GFS2] Further up... |
238 |
goto out; |
b9cb98131 [GFS2] Fix attrib... |
239 |
if (!IS_IMMUTABLE(inode)) { |
10556cb21 ->permission() sa... |
240 |
error = gfs2_permission(inode, MAY_WRITE); |
b9cb98131 [GFS2] Fix attrib... |
241 242 243 |
if (error) goto out; } |
5561093e2 [GFS2] Introduce ... |
244 245 246 247 248 249 250 251 252 253 |
if ((flags ^ new_flags) & GFS2_DIF_JDATA) { if (flags & GFS2_DIF_JDATA) gfs2_log_flush(sdp, ip->i_gl); error = filemap_fdatawrite(inode->i_mapping); if (error) goto out; error = filemap_fdatawait(inode->i_mapping); if (error) goto out; } |
55eccc6d0 [GFS2] Finish off... |
254 |
error = gfs2_trans_begin(sdp, RES_DINODE, 0); |
71b86f562 [GFS2] Further up... |
255 256 |
if (error) goto out; |
55eccc6d0 [GFS2] Finish off... |
257 258 259 |
error = gfs2_meta_inode_buffer(ip, &bh); if (error) goto out_trans_end; |
71b86f562 [GFS2] Further up... |
260 |
gfs2_trans_add_bh(ip->i_gl, bh, 1); |
383f01fbf GFS2: Banish stru... |
261 |
ip->i_diskflags = new_flags; |
539e5d6b7 [GFS2] Change arg... |
262 |
gfs2_dinode_out(ip, bh->b_data); |
71b86f562 [GFS2] Further up... |
263 |
brelse(bh); |
6b124d8db [GFS2] Only set i... |
264 |
gfs2_set_inode_flags(inode); |
5561093e2 [GFS2] Introduce ... |
265 |
gfs2_set_aops(inode); |
55eccc6d0 [GFS2] Finish off... |
266 267 |
out_trans_end: gfs2_trans_end(sdp); |
71b86f562 [GFS2] Further up... |
268 269 |
out: gfs2_glock_dq_uninit(&gh); |
f58ba8891 [GFS2] don't call... |
270 |
out_drop_write: |
2a79f17e4 vfs: mnt_drop_wri... |
271 |
mnt_drop_write_file(filp); |
71b86f562 [GFS2] Further up... |
272 273 |
return error; } |
b09e593d7 [GFS2] Fix a ref ... |
274 |
static int gfs2_set_flags(struct file *filp, u32 __user *ptr) |
71b86f562 [GFS2] Further up... |
275 |
{ |
b9af7ca6d [GFS2] Fix settin... |
276 |
struct inode *inode = filp->f_path.dentry->d_inode; |
128e5ebaf [GFS2] Remove ifl... |
277 |
u32 fsflags, gfsflags; |
7df0e0397 GFS2: Fix permiss... |
278 |
|
128e5ebaf [GFS2] Remove ifl... |
279 |
if (get_user(fsflags, ptr)) |
71b86f562 [GFS2] Further up... |
280 |
return -EFAULT; |
7df0e0397 GFS2: Fix permiss... |
281 |
|
128e5ebaf [GFS2] Remove ifl... |
282 |
gfsflags = fsflags_cvt(fsflags_to_gfs2, fsflags); |
b9af7ca6d [GFS2] Fix settin... |
283 284 285 |
if (!S_ISDIR(inode->i_mode)) { if (gfsflags & GFS2_DIF_INHERIT_JDATA) gfsflags ^= (GFS2_DIF_JDATA | GFS2_DIF_INHERIT_JDATA); |
b9af7ca6d [GFS2] Fix settin... |
286 287 288 |
return do_gfs2_set_flags(filp, gfsflags, ~0); } return do_gfs2_set_flags(filp, gfsflags, ~GFS2_DIF_JDATA); |
71b86f562 [GFS2] Further up... |
289 |
} |
b09e593d7 [GFS2] Fix a ref ... |
290 |
static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
71b86f562 [GFS2] Further up... |
291 292 |
{ switch(cmd) { |
128e5ebaf [GFS2] Remove ifl... |
293 |
case FS_IOC_GETFLAGS: |
b09e593d7 [GFS2] Fix a ref ... |
294 |
return gfs2_get_flags(filp, (u32 __user *)arg); |
128e5ebaf [GFS2] Remove ifl... |
295 |
case FS_IOC_SETFLAGS: |
b09e593d7 [GFS2] Fix a ref ... |
296 |
return gfs2_set_flags(filp, (u32 __user *)arg); |
71b86f562 [GFS2] Further up... |
297 298 299 |
} return -ENOTTY; } |
3cc3f710c [GFS2] Use ->page... |
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
/** * gfs2_allocate_page_backing - Use bmap to allocate blocks * @page: The (locked) page to allocate backing for * * We try to allocate all the blocks required for the page in * one go. This might fail for various reasons, so we keep * trying until all the blocks to back this page are allocated. * If some of the blocks are already allocated, thats ok too. */ static int gfs2_allocate_page_backing(struct page *page) { struct inode *inode = page->mapping->host; struct buffer_head bh; unsigned long size = PAGE_CACHE_SIZE; u64 lblock = page->index << (PAGE_CACHE_SHIFT - inode->i_blkbits); do { bh.b_state = 0; bh.b_size = size; |
e9e1ef2b6 [GFS2] Remove fun... |
320 |
gfs2_block_map(inode, lblock, &bh, 1); |
3cc3f710c [GFS2] Use ->page... |
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
if (!buffer_mapped(&bh)) return -EIO; size -= bh.b_size; lblock += (bh.b_size >> inode->i_blkbits); } while(size > 0); return 0; } /** * gfs2_page_mkwrite - Make a shared, mmap()ed, page writable * @vma: The virtual memory area * @page: The page which is about to become writable * * When the page becomes writable, we need to ensure that we have * blocks allocated on disk to back that page. */ |
c2ec175c3 mm: page_mkwrite ... |
337 |
static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
3cc3f710c [GFS2] Use ->page... |
338 |
{ |
c2ec175c3 mm: page_mkwrite ... |
339 |
struct page *page = vmf->page; |
3cc3f710c [GFS2] Use ->page... |
340 341 342 343 |
struct inode *inode = vma->vm_file->f_path.dentry->d_inode; struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); unsigned long last_index; |
c8f554b94 GFS2: Fix typo in... |
344 |
u64 pos = page->index << PAGE_CACHE_SHIFT; |
3cc3f710c [GFS2] Use ->page... |
345 |
unsigned int data_blocks, ind_blocks, rblocks; |
3cc3f710c [GFS2] Use ->page... |
346 |
struct gfs2_holder gh; |
564e12b11 GFS2: decouple qu... |
347 |
struct gfs2_qadata *qa; |
13d921e37 GFS2: Clean up ->... |
348 |
loff_t size; |
3cc3f710c [GFS2] Use ->page... |
349 |
int ret; |
13d921e37 GFS2: Clean up ->... |
350 351 352 353 354 |
/* Wait if fs is frozen. This is racy so we check again later on * and retry if the fs has been frozen after the page lock has * been acquired */ vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); |
719ee3446 GFS2: high time t... |
355 356 |
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); |
3cc3f710c [GFS2] Use ->page... |
357 358 |
if (ret) goto out; |
9c538837d Fix a minor bug i... |
359 360 |
set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); set_bit(GIF_SW_PAGED, &ip->i_flags); |
13d921e37 GFS2: Clean up ->... |
361 362 363 364 365 366 |
if (!gfs2_write_alloc_required(ip, pos, PAGE_CACHE_SIZE)) { lock_page(page); if (!PageUptodate(page) || page->mapping != inode->i_mapping) { ret = -EAGAIN; unlock_page(page); } |
3cc3f710c [GFS2] Use ->page... |
367 |
goto out_unlock; |
13d921e37 GFS2: Clean up ->... |
368 |
} |
6dbd82248 [GFS2] Reduce ino... |
369 |
ret = -ENOMEM; |
564e12b11 GFS2: decouple qu... |
370 371 |
qa = gfs2_qadata_get(ip); if (qa == NULL) |
6dbd82248 [GFS2] Reduce ino... |
372 |
goto out_unlock; |
d82661d96 [GFS2] Streamline... |
373 |
ret = gfs2_quota_lock_check(ip); |
3cc3f710c [GFS2] Use ->page... |
374 375 |
if (ret) goto out_alloc_put; |
7ed122e42 GFS2: Streamline ... |
376 |
gfs2_write_calc_reserv(ip, PAGE_CACHE_SIZE, &data_blocks, &ind_blocks); |
564e12b11 GFS2: decouple qu... |
377 |
ret = gfs2_inplace_reserve(ip, data_blocks + ind_blocks); |
3cc3f710c [GFS2] Use ->page... |
378 379 380 381 382 383 |
if (ret) goto out_quota_unlock; rblocks = RES_DINODE + ind_blocks; if (gfs2_is_jdata(ip)) rblocks += data_blocks ? data_blocks : 1; |
bf97b6734 GFS2: reserve mor... |
384 |
if (ind_blocks || data_blocks) { |
3cc3f710c [GFS2] Use ->page... |
385 |
rblocks += RES_STATFS + RES_QUOTA; |
54335b1fc GFS2: Cache the m... |
386 |
rblocks += gfs2_rg_blocks(ip); |
bf97b6734 GFS2: reserve mor... |
387 |
} |
3cc3f710c [GFS2] Use ->page... |
388 389 390 391 392 393 |
ret = gfs2_trans_begin(sdp, rblocks, 0); if (ret) goto out_trans_fail; lock_page(page); ret = -EINVAL; |
13d921e37 GFS2: Clean up ->... |
394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
size = i_size_read(inode); last_index = (size - 1) >> PAGE_CACHE_SHIFT; /* Check page index against inode size */ if (size == 0 || (page->index > last_index)) goto out_trans_end; ret = -EAGAIN; /* If truncated, we must retry the operation, we may have raced * with the glock demotion code. */ if (!PageUptodate(page) || page->mapping != inode->i_mapping) goto out_trans_end; /* Unstuff, if required, and allocate backing blocks for page */ |
b7fe2e391 [GFS2] Fix page_m... |
408 |
ret = 0; |
13d921e37 GFS2: Clean up ->... |
409 |
if (gfs2_is_stuffed(ip)) |
3cc3f710c [GFS2] Use ->page... |
410 |
ret = gfs2_unstuff_dinode(ip, page); |
13d921e37 GFS2: Clean up ->... |
411 412 |
if (ret == 0) ret = gfs2_allocate_page_backing(page); |
3cc3f710c [GFS2] Use ->page... |
413 |
|
13d921e37 GFS2: Clean up ->... |
414 415 416 |
out_trans_end: if (ret) unlock_page(page); |
3cc3f710c [GFS2] Use ->page... |
417 418 419 420 421 422 |
gfs2_trans_end(sdp); out_trans_fail: gfs2_inplace_release(ip); out_quota_unlock: gfs2_quota_unlock(ip); out_alloc_put: |
564e12b11 GFS2: decouple qu... |
423 |
gfs2_qadata_put(ip); |
3cc3f710c [GFS2] Use ->page... |
424 425 426 427 |
out_unlock: gfs2_glock_dq(&gh); out: gfs2_holder_uninit(&gh); |
13d921e37 GFS2: Clean up ->... |
428 429 430 431 432 433 434 435 436 437 438 |
if (ret == 0) { set_page_dirty(page); /* This check must be post dropping of transaction lock */ if (inode->i_sb->s_frozen == SB_UNFROZEN) { wait_on_page_writeback(page); } else { ret = -EAGAIN; unlock_page(page); } } return block_page_mkwrite_return(ret); |
3cc3f710c [GFS2] Use ->page... |
439 |
} |
f0f37e2f7 const: mark struc... |
440 |
static const struct vm_operations_struct gfs2_vm_ops = { |
3cc3f710c [GFS2] Use ->page... |
441 442 443 |
.fault = filemap_fault, .page_mkwrite = gfs2_page_mkwrite, }; |
b3b94faa5 [GFS2] The core o... |
444 445 446 447 448 |
/** * gfs2_mmap - * @file: The file to map * @vma: The VMA which described the mapping * |
48bf2b171 GFS2: Something n... |
449 450 451 452 453 |
* There is no need to get a lock here unless we should be updating * atime. We ignore any locking errors since the only consequence is * a missed atime update (which will just be deferred until later). * * Returns: 0 |
b3b94faa5 [GFS2] The core o... |
454 455 456 457 |
*/ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) { |
feaa7bba0 [GFS2] Fix unlink... |
458 |
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); |
b3b94faa5 [GFS2] The core o... |
459 |
|
b9c93bb7d GFS2: Improve clu... |
460 461 |
if (!(file->f_flags & O_NOATIME) && !IS_NOATIME(&ip->i_inode)) { |
48bf2b171 GFS2: Something n... |
462 463 |
struct gfs2_holder i_gh; int error; |
b3b94faa5 [GFS2] The core o... |
464 |
|
b9c93bb7d GFS2: Improve clu... |
465 |
gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); |
48bf2b171 GFS2: Something n... |
466 |
error = gfs2_glock_nq(&i_gh); |
b9c93bb7d GFS2: Improve clu... |
467 468 469 470 471 472 473 |
if (error == 0) { file_accessed(file); gfs2_glock_dq(&i_gh); } gfs2_holder_uninit(&i_gh); if (error) return error; |
48bf2b171 GFS2: Something n... |
474 |
} |
3cc3f710c [GFS2] Use ->page... |
475 |
vma->vm_ops = &gfs2_vm_ops; |
48bf2b171 GFS2: Something n... |
476 |
vma->vm_flags |= VM_CAN_NONLINEAR; |
b3b94faa5 [GFS2] The core o... |
477 |
|
48bf2b171 GFS2: Something n... |
478 |
return 0; |
b3b94faa5 [GFS2] The core o... |
479 480 481 482 483 484 485 486 487 488 489 490 |
} /** * gfs2_open - open a file * @inode: the inode to open * @file: the struct file for this opening * * Returns: errno */ static int gfs2_open(struct inode *inode, struct file *file) { |
feaa7bba0 [GFS2] Fix unlink... |
491 |
struct gfs2_inode *ip = GFS2_I(inode); |
b3b94faa5 [GFS2] The core o... |
492 493 494 |
struct gfs2_holder i_gh; struct gfs2_file *fp; int error; |
b3b94faa5 [GFS2] The core o... |
495 496 497 |
fp = kzalloc(sizeof(struct gfs2_file), GFP_KERNEL); if (!fp) return -ENOMEM; |
f55ab26a8 [GFS2] Use mutice... |
498 |
mutex_init(&fp->f_fl_mutex); |
b3b94faa5 [GFS2] The core o... |
499 |
|
feaa7bba0 [GFS2] Fix unlink... |
500 |
gfs2_assert_warn(GFS2_SB(inode), !file->private_data); |
5c676f6d3 [GFS2] Macros rem... |
501 |
file->private_data = fp; |
b3b94faa5 [GFS2] The core o... |
502 |
|
b60623c23 [GFS2] Shrink gfs... |
503 |
if (S_ISREG(ip->i_inode.i_mode)) { |
b3b94faa5 [GFS2] The core o... |
504 505 506 507 508 509 |
error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); if (error) goto fail; if (!(file->f_flags & O_LARGEFILE) && |
a2e0f7993 GFS2: Remove i_di... |
510 |
i_size_read(inode) > MAX_NON_LFS) { |
a9c62a18a fs: correct SuS c... |
511 |
error = -EOVERFLOW; |
b3b94faa5 [GFS2] The core o... |
512 513 |
goto fail_gunlock; } |
b3b94faa5 [GFS2] The core o... |
514 515 516 517 |
gfs2_glock_dq_uninit(&i_gh); } return 0; |
420b9e5e4 [GFS2] Tidy up in... |
518 |
fail_gunlock: |
b3b94faa5 [GFS2] The core o... |
519 |
gfs2_glock_dq_uninit(&i_gh); |
420b9e5e4 [GFS2] Tidy up in... |
520 |
fail: |
5c676f6d3 [GFS2] Macros rem... |
521 |
file->private_data = NULL; |
b3b94faa5 [GFS2] The core o... |
522 |
kfree(fp); |
b3b94faa5 [GFS2] The core o... |
523 524 525 526 527 528 529 530 531 532 533 534 535 |
return error; } /** * gfs2_close - called to close a struct file * @inode: the inode the struct file belongs to * @file: the struct file being closed * * Returns: errno */ static int gfs2_close(struct inode *inode, struct file *file) { |
5c676f6d3 [GFS2] Macros rem... |
536 |
struct gfs2_sbd *sdp = inode->i_sb->s_fs_info; |
b3b94faa5 [GFS2] The core o... |
537 |
struct gfs2_file *fp; |
5c676f6d3 [GFS2] Macros rem... |
538 539 |
fp = file->private_data; file->private_data = NULL; |
b3b94faa5 [GFS2] The core o... |
540 541 542 543 544 545 546 547 548 549 550 |
if (gfs2_assert_warn(sdp, fp)) return -EIO; kfree(fp); return 0; } /** * gfs2_fsync - sync the dirty data for a file (across the cluster) |
02c24a821 fs: push i_mutex ... |
551 552 553 |
* @file: the file that points to the dentry * @start: the start position in the file to sync * @end: the end position in the file to sync |
dba898b02 GFS2: Clean up fs... |
554 |
* @datasync: set if we can ignore timestamp changes |
b3b94faa5 [GFS2] The core o... |
555 |
* |
2f0264d59 GFS2: Split data ... |
556 557 558 559 560 561 562 563 564 565 |
* We split the data flushing here so that we don't wait for the data * until after we've also sent the metadata to disk. Note that for * data=ordered, we will write & wait for the data at the log flush * stage anyway, so this is unlikely to make much of a difference * except in the data=writeback case. * * If the fdatawrite fails due to any reason except -EIO, we will * continue the remainder of the fsync, although we'll still report * the error at the end. This is to match filemap_write_and_wait_range() * behaviour. |
34126f9f4 [GFS2] Change gfs... |
566 |
* |
b3b94faa5 [GFS2] The core o... |
567 568 |
* Returns: errno */ |
02c24a821 fs: push i_mutex ... |
569 570 |
static int gfs2_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
b3b94faa5 [GFS2] The core o... |
571 |
{ |
2f0264d59 GFS2: Split data ... |
572 573 |
struct address_space *mapping = file->f_mapping; struct inode *inode = mapping->host; |
33c3de328 [GFS2] Don't flus... |
574 |
int sync_state = inode->i_state & (I_DIRTY_SYNC|I_DIRTY_DATASYNC); |
dba898b02 GFS2: Clean up fs... |
575 |
struct gfs2_inode *ip = GFS2_I(inode); |
87654896c GFS2: More automa... |
576 |
int ret = 0, ret1 = 0; |
b3b94faa5 [GFS2] The core o... |
577 |
|
2f0264d59 GFS2: Split data ... |
578 579 580 581 582 |
if (mapping->nrpages) { ret1 = filemap_fdatawrite_range(mapping, start, end); if (ret1 == -EIO) return ret1; } |
02c24a821 fs: push i_mutex ... |
583 |
|
dba898b02 GFS2: Clean up fs... |
584 585 |
if (datasync) sync_state &= ~I_DIRTY_SYNC; |
b3b94faa5 [GFS2] The core o... |
586 |
|
dba898b02 GFS2: Clean up fs... |
587 588 |
if (sync_state) { ret = sync_inode_metadata(inode, 1); |
b5b24d7ae GFS2: Fix AIL flu... |
589 |
if (ret) |
dba898b02 GFS2: Clean up fs... |
590 |
return ret; |
f18185291 GFS2: Fix bug tra... |
591 592 |
if (gfs2_is_jdata(ip)) filemap_write_and_wait(mapping); |
b5b24d7ae GFS2: Fix AIL flu... |
593 |
gfs2_ail_flush(ip->i_gl, 1); |
33c3de328 [GFS2] Don't flus... |
594 |
} |
2f0264d59 GFS2: Split data ... |
595 596 597 598 |
if (mapping->nrpages) ret = filemap_fdatawait_range(mapping, start, end); return ret ? ret : ret1; |
b3b94faa5 [GFS2] The core o... |
599 |
} |
56aa616a0 GFS2: Ensure upto... |
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 |
/** * gfs2_file_aio_write - Perform a write to a file * @iocb: The io context * @iov: The data to write * @nr_segs: Number of @iov segments * @pos: The file position * * We have to do a lock/unlock here to refresh the inode size for * O_APPEND writes, otherwise we can land up writing at the wrong * offset. There is still a race, but provided the app is using its * own file locking, this will make O_APPEND work as expected. * */ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct file *file = iocb->ki_filp; if (file->f_flags & O_APPEND) { struct dentry *dentry = file->f_dentry; struct gfs2_inode *ip = GFS2_I(dentry->d_inode); struct gfs2_holder gh; int ret; ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); if (ret) return ret; gfs2_glock_dq_uninit(&gh); } return generic_file_aio_write(iocb, iov, nr_segs, pos); } |
2fe17c107 fallocate should ... |
633 634 635 636 637 638 |
static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len, int mode) { struct gfs2_inode *ip = GFS2_I(inode); struct buffer_head *dibh; int error; |
64dd153c8 GFS2: rewrite fal... |
639 640 |
unsigned int nr_blks; sector_t lblock = offset >> inode->i_blkbits; |
2fe17c107 fallocate should ... |
641 642 643 |
error = gfs2_meta_inode_buffer(ip, &dibh); if (unlikely(error)) |
64dd153c8 GFS2: rewrite fal... |
644 |
return error; |
2fe17c107 fallocate should ... |
645 646 647 648 649 650 651 652 |
gfs2_trans_add_bh(ip->i_gl, dibh, 1); if (gfs2_is_stuffed(ip)) { error = gfs2_unstuff_dinode(ip, NULL); if (unlikely(error)) goto out; } |
64dd153c8 GFS2: rewrite fal... |
653 654 655 656 |
while (len) { struct buffer_head bh_map = { .b_state = 0, .b_blocknr = 0 }; bh_map.b_size = len; set_buffer_zeronew(&bh_map); |
2fe17c107 fallocate should ... |
657 |
|
64dd153c8 GFS2: rewrite fal... |
658 659 660 661 662 663 664 665 666 667 |
error = gfs2_block_map(inode, lblock, &bh_map, 1); if (unlikely(error)) goto out; len -= bh_map.b_size; nr_blks = bh_map.b_size >> inode->i_blkbits; lblock += nr_blks; if (!buffer_new(&bh_map)) continue; if (unlikely(!buffer_zeronew(&bh_map))) { error = -EIO; |
2fe17c107 fallocate should ... |
668 |
goto out; |
64dd153c8 GFS2: rewrite fal... |
669 |
} |
2fe17c107 fallocate should ... |
670 |
} |
64dd153c8 GFS2: rewrite fal... |
671 672 |
if (offset + len > inode->i_size && !(mode & FALLOC_FL_KEEP_SIZE)) i_size_write(inode, offset + len); |
2fe17c107 fallocate should ... |
673 |
|
2fe17c107 fallocate should ... |
674 |
mark_inode_dirty(inode); |
2fe17c107 fallocate should ... |
675 |
out: |
64dd153c8 GFS2: rewrite fal... |
676 |
brelse(dibh); |
2fe17c107 fallocate should ... |
677 678 679 680 681 682 683 |
return error; } static void calc_max_reserv(struct gfs2_inode *ip, loff_t max, loff_t *len, unsigned int *data_blocks, unsigned int *ind_blocks) { const struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
54335b1fc GFS2: Cache the m... |
684 |
unsigned int max_blocks = ip->i_rgd->rd_free_clone; |
2fe17c107 fallocate should ... |
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 |
unsigned int tmp, max_data = max_blocks - 3 * (sdp->sd_max_height - 1); for (tmp = max_data; tmp > sdp->sd_diptrs;) { tmp = DIV_ROUND_UP(tmp, sdp->sd_inptrs); max_data -= tmp; } /* This calculation isn't the exact reverse of gfs2_write_calc_reserve, so it might end up with fewer data blocks */ if (max_data <= *data_blocks) return; *data_blocks = max_data; *ind_blocks = max_blocks - max_data; *len = ((loff_t)max_data - 3) << sdp->sd_sb.sb_bsize_shift; if (*len > max) { *len = max; gfs2_write_calc_reserv(ip, max, data_blocks, ind_blocks); } } static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t len) { struct inode *inode = file->f_path.dentry->d_inode; struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_inode *ip = GFS2_I(inode); unsigned int data_blocks = 0, ind_blocks = 0, rblocks; loff_t bytes, max_bytes; |
564e12b11 GFS2: decouple qu... |
712 |
struct gfs2_qadata *qa; |
2fe17c107 fallocate should ... |
713 |
int error; |
4442f2e03 GFS2: O_(D)SYNC s... |
714 715 |
const loff_t pos = offset; const loff_t count = len; |
6905d9e4d GFS2: make sure f... |
716 |
loff_t bsize_mask = ~((loff_t)sdp->sd_sb.sb_bsize - 1); |
2fe17c107 fallocate should ... |
717 |
loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift; |
64dd153c8 GFS2: rewrite fal... |
718 |
loff_t max_chunk_size = UINT_MAX & bsize_mask; |
2fe17c107 fallocate should ... |
719 720 721 722 723 |
next = (next + 1) << sdp->sd_sb.sb_bsize_shift; /* We only support the FALLOC_FL_KEEP_SIZE mode */ if (mode & ~FALLOC_FL_KEEP_SIZE) return -EOPNOTSUPP; |
6905d9e4d GFS2: make sure f... |
724 |
offset &= bsize_mask; |
2fe17c107 fallocate should ... |
725 726 727 728 729 |
len = next - offset; bytes = sdp->sd_max_rg_data * sdp->sd_sb.sb_bsize / 2; if (!bytes) bytes = UINT_MAX; |
6905d9e4d GFS2: make sure f... |
730 731 732 |
bytes &= bsize_mask; if (bytes == 0) bytes = sdp->sd_sb.sb_bsize; |
2fe17c107 fallocate should ... |
733 734 735 736 737 738 739 740 741 742 743 744 |
gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh); error = gfs2_glock_nq(&ip->i_gh); if (unlikely(error)) goto out_uninit; if (!gfs2_write_alloc_required(ip, offset, len)) goto out_unlock; while (len > 0) { if (len < bytes) bytes = len; |
564e12b11 GFS2: decouple qu... |
745 746 |
qa = gfs2_qadata_get(ip); if (!qa) { |
2fe17c107 fallocate should ... |
747 748 749 750 751 752 753 754 755 756 |
error = -ENOMEM; goto out_unlock; } error = gfs2_quota_lock_check(ip); if (error) goto out_alloc_put; retry: gfs2_write_calc_reserv(ip, bytes, &data_blocks, &ind_blocks); |
564e12b11 GFS2: decouple qu... |
757 |
error = gfs2_inplace_reserve(ip, data_blocks + ind_blocks); |
2fe17c107 fallocate should ... |
758 759 760 |
if (error) { if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) { bytes >>= 1; |
6905d9e4d GFS2: make sure f... |
761 762 763 |
bytes &= bsize_mask; if (bytes == 0) bytes = sdp->sd_sb.sb_bsize; |
2fe17c107 fallocate should ... |
764 765 766 767 768 |
goto retry; } goto out_qunlock; } max_bytes = bytes; |
64dd153c8 GFS2: rewrite fal... |
769 770 |
calc_max_reserv(ip, (len > max_chunk_size)? max_chunk_size: len, &max_bytes, &data_blocks, &ind_blocks); |
2fe17c107 fallocate should ... |
771 772 |
rblocks = RES_DINODE + ind_blocks + RES_STATFS + RES_QUOTA + |
54335b1fc GFS2: Cache the m... |
773 |
RES_RG_HDR + gfs2_rg_blocks(ip); |
2fe17c107 fallocate should ... |
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 |
if (gfs2_is_jdata(ip)) rblocks += data_blocks ? data_blocks : 1; error = gfs2_trans_begin(sdp, rblocks, PAGE_CACHE_SIZE/sdp->sd_sb.sb_bsize); if (error) goto out_trans_fail; error = fallocate_chunk(inode, offset, max_bytes, mode); gfs2_trans_end(sdp); if (error) goto out_trans_fail; len -= max_bytes; offset += max_bytes; gfs2_inplace_release(ip); gfs2_quota_unlock(ip); |
564e12b11 GFS2: decouple qu... |
792 |
gfs2_qadata_put(ip); |
2fe17c107 fallocate should ... |
793 |
} |
4442f2e03 GFS2: O_(D)SYNC s... |
794 795 796 |
if (error == 0) error = generic_write_sync(file, pos, count); |
2fe17c107 fallocate should ... |
797 798 799 800 801 802 803 |
goto out_unlock; out_trans_fail: gfs2_inplace_release(ip); out_qunlock: gfs2_quota_unlock(ip); out_alloc_put: |
564e12b11 GFS2: decouple qu... |
804 |
gfs2_qadata_put(ip); |
2fe17c107 fallocate should ... |
805 806 807 808 809 810 |
out_unlock: gfs2_glock_dq(&ip->i_gh); out_uninit: gfs2_holder_uninit(&ip->i_gh); return error; } |
f057f6cdf GFS2: Merge lock_... |
811 |
#ifdef CONFIG_GFS2_FS_LOCKING_DLM |
b3b94faa5 [GFS2] The core o... |
812 |
/** |
60446067b gfs2: stop giving... |
813 814 815 816 817 |
* gfs2_setlease - acquire/release a file lease * @file: the file pointer * @arg: lease type * @fl: file lock * |
f057f6cdf GFS2: Merge lock_... |
818 819 820 821 |
* We don't currently have a way to enforce a lease across the whole * cluster; until we do, disable leases (by just returning -EINVAL), * unless the administrator has requested purely local locking. * |
b89f43213 fs/locks.c: prepa... |
822 823 |
* Locking: called under lock_flocks * |
60446067b gfs2: stop giving... |
824 825 826 827 828 |
* Returns: errno */ static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl) { |
f057f6cdf GFS2: Merge lock_... |
829 |
return -EINVAL; |
da755fdb4 [GFS2] Remove lm.... |
830 |
} |
60446067b gfs2: stop giving... |
831 |
/** |
b3b94faa5 [GFS2] The core o... |
832 833 834 835 836 837 838 839 840 841 |
* gfs2_lock - acquire/release a posix lock on a file * @file: the file pointer * @cmd: either modify or retrieve lock state, possibly wait * @fl: type and range of lock * * Returns: errno */ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) { |
feaa7bba0 [GFS2] Fix unlink... |
842 843 |
struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host); |
f057f6cdf GFS2: Merge lock_... |
844 |
struct lm_lockstruct *ls = &sdp->sd_lockstruct; |
b3b94faa5 [GFS2] The core o... |
845 |
|
b3b94faa5 [GFS2] The core o... |
846 847 |
if (!(fl->fl_flags & FL_POSIX)) return -ENOLCK; |
720e77492 GFS2: Skip check ... |
848 |
if (__mandatory_lock(&ip->i_inode) && fl->fl_type != F_UNLCK) |
b3b94faa5 [GFS2] The core o... |
849 |
return -ENOLCK; |
586759f03 gfs2: nfs lock su... |
850 851 852 853 854 |
if (cmd == F_CANCELLK) { /* Hack: */ cmd = F_SETLK; fl->fl_type = F_UNLCK; } |
f057f6cdf GFS2: Merge lock_... |
855 856 |
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) return -EIO; |
b3b94faa5 [GFS2] The core o... |
857 |
if (IS_GETLK(cmd)) |
f057f6cdf GFS2: Merge lock_... |
858 |
return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl); |
b3b94faa5 [GFS2] The core o... |
859 |
else if (fl->fl_type == F_UNLCK) |
f057f6cdf GFS2: Merge lock_... |
860 |
return dlm_posix_unlock(ls->ls_dlm, ip->i_no_addr, file, fl); |
b3b94faa5 [GFS2] The core o... |
861 |
else |
f057f6cdf GFS2: Merge lock_... |
862 |
return dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl); |
b3b94faa5 [GFS2] The core o... |
863 |
} |
b3b94faa5 [GFS2] The core o... |
864 865 |
static int do_flock(struct file *file, int cmd, struct file_lock *fl) { |
5c676f6d3 [GFS2] Macros rem... |
866 |
struct gfs2_file *fp = file->private_data; |
b3b94faa5 [GFS2] The core o... |
867 |
struct gfs2_holder *fl_gh = &fp->f_fl_gh; |
81454098f [PATCH] struct pa... |
868 |
struct gfs2_inode *ip = GFS2_I(file->f_path.dentry->d_inode); |
b3b94faa5 [GFS2] The core o... |
869 870 871 872 873 874 |
struct gfs2_glock *gl; unsigned int state; int flags; int error = 0; state = (fl->fl_type == F_WRLCK) ? LM_ST_EXCLUSIVE : LM_ST_SHARED; |
6802e3400 [GFS2] Clean up t... |
875 |
flags = (IS_SETLKW(cmd) ? 0 : LM_FLAG_TRY) | GL_EXACT | GL_NOCACHE; |
b3b94faa5 [GFS2] The core o... |
876 |
|
f55ab26a8 [GFS2] Use mutice... |
877 |
mutex_lock(&fp->f_fl_mutex); |
b3b94faa5 [GFS2] The core o... |
878 879 880 881 882 |
gl = fl_gh->gh_gl; if (gl) { if (fl_gh->gh_state == state) goto out; |
b3b94faa5 [GFS2] The core o... |
883 |
flock_lock_file_wait(file, |
907b9bceb [GFS2/DLM] Fix tr... |
884 |
&(struct file_lock){.fl_type = F_UNLCK}); |
b4c20166d [GFS2] flocks fro... |
885 886 |
gfs2_glock_dq_wait(fl_gh); gfs2_holder_reinit(state, flags, fl_gh); |
b3b94faa5 [GFS2] The core o... |
887 |
} else { |
6802e3400 [GFS2] Clean up t... |
888 889 |
error = gfs2_glock_get(GFS2_SB(&ip->i_inode), ip->i_no_addr, &gfs2_flock_glops, CREATE, &gl); |
b3b94faa5 [GFS2] The core o... |
890 891 |
if (error) goto out; |
b4c20166d [GFS2] flocks fro... |
892 893 |
gfs2_holder_init(gl, state, flags, fl_gh); gfs2_glock_put(gl); |
b3b94faa5 [GFS2] The core o... |
894 |
} |
b3b94faa5 [GFS2] The core o... |
895 896 897 898 899 900 901 |
error = gfs2_glock_nq(fl_gh); if (error) { gfs2_holder_uninit(fl_gh); if (error == GLR_TRYFAILED) error = -EAGAIN; } else { error = flock_lock_file_wait(file, fl); |
feaa7bba0 [GFS2] Fix unlink... |
902 |
gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error); |
b3b94faa5 [GFS2] The core o... |
903 |
} |
420b9e5e4 [GFS2] Tidy up in... |
904 |
out: |
f55ab26a8 [GFS2] Use mutice... |
905 |
mutex_unlock(&fp->f_fl_mutex); |
b3b94faa5 [GFS2] The core o... |
906 907 908 909 910 |
return error; } static void do_unflock(struct file *file, struct file_lock *fl) { |
5c676f6d3 [GFS2] Macros rem... |
911 |
struct gfs2_file *fp = file->private_data; |
b3b94faa5 [GFS2] The core o... |
912 |
struct gfs2_holder *fl_gh = &fp->f_fl_gh; |
f55ab26a8 [GFS2] Use mutice... |
913 |
mutex_lock(&fp->f_fl_mutex); |
b3b94faa5 [GFS2] The core o... |
914 |
flock_lock_file_wait(file, fl); |
0a33443b3 GFS2: Remove pote... |
915 916 917 918 |
if (fl_gh->gh_gl) { gfs2_glock_dq_wait(fl_gh); gfs2_holder_uninit(fl_gh); } |
f55ab26a8 [GFS2] Use mutice... |
919 |
mutex_unlock(&fp->f_fl_mutex); |
b3b94faa5 [GFS2] The core o... |
920 921 922 923 924 925 926 927 928 929 930 931 932 |
} /** * gfs2_flock - acquire/release a flock lock on a file * @file: the file pointer * @cmd: either modify or retrieve lock state, possibly wait * @fl: type and range of lock * * Returns: errno */ static int gfs2_flock(struct file *file, int cmd, struct file_lock *fl) { |
b3b94faa5 [GFS2] The core o... |
933 934 |
if (!(fl->fl_flags & FL_FLOCK)) return -ENOLCK; |
a12af1ebe GFS2: smbd procce... |
935 936 |
if (fl->fl_type & LOCK_MAND) return -EOPNOTSUPP; |
b3b94faa5 [GFS2] The core o... |
937 |
|
b3b94faa5 [GFS2] The core o... |
938 939 940 |
if (fl->fl_type == F_UNLCK) { do_unflock(file, fl); return 0; |
d00223f16 [GFS2] Fix code s... |
941 |
} else { |
b3b94faa5 [GFS2] The core o... |
942 |
return do_flock(file, cmd, fl); |
d00223f16 [GFS2] Fix code s... |
943 |
} |
b3b94faa5 [GFS2] The core o... |
944 |
} |
10d219880 GFS2: cleanup fil... |
945 |
const struct file_operations gfs2_file_fops = { |
26c1a5741 [GFS2] More code ... |
946 |
.llseek = gfs2_llseek, |
d00223f16 [GFS2] Fix code s... |
947 |
.read = do_sync_read, |
26c1a5741 [GFS2] More code ... |
948 |
.aio_read = generic_file_aio_read, |
d00223f16 [GFS2] Fix code s... |
949 |
.write = do_sync_write, |
56aa616a0 GFS2: Ensure upto... |
950 |
.aio_write = gfs2_file_aio_write, |
26c1a5741 [GFS2] More code ... |
951 952 953 954 955 956 |
.unlocked_ioctl = gfs2_ioctl, .mmap = gfs2_mmap, .open = gfs2_open, .release = gfs2_close, .fsync = gfs2_fsync, .lock = gfs2_lock, |
26c1a5741 [GFS2] More code ... |
957 958 959 |
.flock = gfs2_flock, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, |
60446067b gfs2: stop giving... |
960 |
.setlease = gfs2_setlease, |
2fe17c107 fallocate should ... |
961 |
.fallocate = gfs2_fallocate, |
b3b94faa5 [GFS2] The core o... |
962 |
}; |
10d219880 GFS2: cleanup fil... |
963 |
const struct file_operations gfs2_dir_fops = { |
26c1a5741 [GFS2] More code ... |
964 965 966 967 968 969 970 |
.readdir = gfs2_readdir, .unlocked_ioctl = gfs2_ioctl, .open = gfs2_open, .release = gfs2_close, .fsync = gfs2_fsync, .lock = gfs2_lock, .flock = gfs2_flock, |
6038f373a llseek: automatic... |
971 |
.llseek = default_llseek, |
b3b94faa5 [GFS2] The core o... |
972 |
}; |
f057f6cdf GFS2: Merge lock_... |
973 |
#endif /* CONFIG_GFS2_FS_LOCKING_DLM */ |
10d219880 GFS2: cleanup fil... |
974 |
const struct file_operations gfs2_file_fops_nolock = { |
c97bfe435 [GFS2] Remove loc... |
975 976 977 978 |
.llseek = gfs2_llseek, .read = do_sync_read, .aio_read = generic_file_aio_read, .write = do_sync_write, |
56aa616a0 GFS2: Ensure upto... |
979 |
.aio_write = gfs2_file_aio_write, |
c97bfe435 [GFS2] Remove loc... |
980 981 982 983 984 985 986 |
.unlocked_ioctl = gfs2_ioctl, .mmap = gfs2_mmap, .open = gfs2_open, .release = gfs2_close, .fsync = gfs2_fsync, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, |
f057f6cdf GFS2: Merge lock_... |
987 |
.setlease = generic_setlease, |
2fe17c107 fallocate should ... |
988 |
.fallocate = gfs2_fallocate, |
c97bfe435 [GFS2] Remove loc... |
989 |
}; |
10d219880 GFS2: cleanup fil... |
990 |
const struct file_operations gfs2_dir_fops_nolock = { |
c97bfe435 [GFS2] Remove loc... |
991 992 993 994 995 |
.readdir = gfs2_readdir, .unlocked_ioctl = gfs2_ioctl, .open = gfs2_open, .release = gfs2_close, .fsync = gfs2_fsync, |
6038f373a llseek: automatic... |
996 |
.llseek = default_llseek, |
c97bfe435 [GFS2] Remove loc... |
997 |
}; |