ops_file.c 15.1 KB
Newer Older
David Teigland's avatar
David Teigland committed
1
2
/*
 * Copyright (C) Sistina Software, Inc.  1997-2003 All rights reserved.
3
 * Copyright (C) 2004-2006 Red Hat, Inc.  All rights reserved.
David Teigland's avatar
David Teigland committed
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
7
 * of the GNU General Public License version 2.
David Teigland's avatar
David Teigland committed
8
9
10
11
12
13
14
15
16
17
18
19
 */

#include <linux/sched.h>
#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>
#include <linux/smp_lock.h>
20
#include <linux/fs.h>
21
#include <linux/gfs2_ondisk.h>
22
23
#include <linux/ext2_fs.h>
#include <linux/crc32.h>
24
#include <linux/iflags.h>
25
#include <linux/lm_interface.h>
David Teigland's avatar
David Teigland committed
26
27
28
#include <asm/uaccess.h>

#include "gfs2.h"
29
#include "incore.h"
David Teigland's avatar
David Teigland committed
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "bmap.h"
#include "dir.h"
#include "glock.h"
#include "glops.h"
#include "inode.h"
#include "lm.h"
#include "log.h"
#include "meta_io.h"
#include "ops_file.h"
#include "ops_vm.h"
#include "quota.h"
#include "rgrp.h"
#include "trans.h"
43
#include "util.h"
44
#include "eaops.h"
David Teigland's avatar
David Teigland committed
45
46
47
48
49
50
51
52
53
54

/* For regular, non-NFS */
struct filldir_reg {
	struct gfs2_sbd *fdr_sbd;
	int fdr_prefetch;

	filldir_t fdr_filldir;
	void *fdr_opaque;
};

55
56
57
58
59
60
/*
 * Most fields left uninitialised to catch anybody who tries to
 * use them. f_flags set to prevent file_accessed() from touching
 * any other part of this. Its use is purely as a flag so that we
 * know (in readpage()) whether or not do to locking.
 */
61
struct file gfs2_internal_file_sentinel = {
62
63
64
	.f_flags = O_NOATIME|O_RDONLY,
};

65
66
67
68
69
70
71
72
73
74
75
static int gfs2_read_actor(read_descriptor_t *desc, struct page *page,
			   unsigned long offset, unsigned long size)
{
	char *kaddr;
	unsigned long count = desc->count;

	if (size > count)
		size = count;

	kaddr = kmap(page);
	memcpy(desc->arg.buf, kaddr + offset, size);
76
	kunmap(page);
77

78
79
80
81
	desc->count = count - size;
	desc->written += size;
	desc->arg.buf += size;
	return size;
82
83
84
85
86
}

int gfs2_internal_read(struct gfs2_inode *ip, struct file_ra_state *ra_state,
		       char *buf, loff_t *pos, unsigned size)
{
87
	struct inode *inode = &ip->i_inode;
88
89
90
91
92
	read_descriptor_t desc;
	desc.written = 0;
	desc.arg.buf = buf;
	desc.count = size;
	desc.error = 0;
93
	do_generic_mapping_read(inode->i_mapping, ra_state,
94
				&gfs2_internal_file_sentinel, pos, &desc,
95
				gfs2_read_actor);
96
97
	return desc.written ? desc.written : desc.error;
}
David Teigland's avatar
David Teigland committed
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

/**
 * 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)
{
113
	struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
David Teigland's avatar
David Teigland committed
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
	struct gfs2_holder i_gh;
	loff_t error;

	if (origin == 2) {
		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
					   &i_gh);
		if (!error) {
			error = remote_llseek(file, offset, origin);
			gfs2_glock_dq_uninit(&i_gh);
		}
	} else
		error = remote_llseek(file, offset, origin);

	return error;
}

/**
131
 * filldir_func - Report a directory entry to the caller of gfs2_dir_read()
David Teigland's avatar
David Teigland committed
132
133
134
135
136
137
138
139
140
141
 * @opaque: opaque data used by the function
 * @name: the name of the directory entry
 * @length: the length of the name
 * @offset: the entry's offset in the directory
 * @inum: the inode number the entry points to
 * @type: the type of inode the entry points to
 *
 * Returns: 0 on success, 1 if buffer full
 */

142
143
144
static int filldir_func(void *opaque, const char *name, unsigned int length,
			u64 offset, struct gfs2_inum *inum,
			unsigned int type)
David Teigland's avatar
David Teigland committed
145
146
147
148
149
150
{
	struct filldir_reg *fdr = (struct filldir_reg *)opaque;
	struct gfs2_sbd *sdp = fdr->fdr_sbd;
	int error;

	error = fdr->fdr_filldir(fdr->fdr_opaque, name, length, offset,
151
				 inum->no_addr, type);
David Teigland's avatar
David Teigland committed
152
153
154
155
	if (error)
		return 1;

	if (fdr->fdr_prefetch && !(length == 1 && *name == '.')) {
156
		gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_inode_glops,
David Teigland's avatar
David Teigland committed
157
				       LM_ST_SHARED, LM_FLAG_TRY | LM_FLAG_ANY);
158
		gfs2_glock_prefetch_num(sdp, inum->no_addr, &gfs2_iopen_glops,
David Teigland's avatar
David Teigland committed
159
160
161
162
163
164
165
				       LM_ST_SHARED, LM_FLAG_TRY);
	}

	return 0;
}

/**
166
 * gfs2_readdir - Read directory entries from a directory
David Teigland's avatar
David Teigland committed
167
168
169
170
171
172
173
 * @file: The directory to read from
 * @dirent: Buffer for dirents
 * @filldir: Function used to do the copying
 *
 * Returns: errno
 */

174
static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir)
David Teigland's avatar
David Teigland committed
175
{
176
	struct inode *dir = file->f_mapping->host;
177
	struct gfs2_inode *dip = GFS2_I(dir);
David Teigland's avatar
David Teigland committed
178
179
	struct filldir_reg fdr;
	struct gfs2_holder d_gh;
180
	u64 offset = file->f_pos;
David Teigland's avatar
David Teigland committed
181
182
	int error;

183
	fdr.fdr_sbd = GFS2_SB(dir);
David Teigland's avatar
David Teigland committed
184
185
186
187
188
189
190
191
192
193
194
	fdr.fdr_prefetch = 1;
	fdr.fdr_filldir = filldir;
	fdr.fdr_opaque = dirent;

	gfs2_holder_init(dip->i_gl, LM_ST_SHARED, GL_ATIME, &d_gh);
	error = gfs2_glock_nq_atime(&d_gh);
	if (error) {
		gfs2_holder_uninit(&d_gh);
		return error;
	}

195
	error = gfs2_dir_read(dir, &offset, &fdr, filldir_func);
David Teigland's avatar
David Teigland committed
196
197
198
199
200
201
202
203
204

	gfs2_glock_dq_uninit(&d_gh);

	file->f_pos = offset;

	return error;
}


205
206
207
208
209
210
211
212
static const u32 iflags_to_gfs2[32] = {
	[iflag_Sync] = GFS2_DIF_SYNC,
	[iflag_Immutable] = GFS2_DIF_IMMUTABLE,
	[iflag_Append] = GFS2_DIF_APPENDONLY,
	[iflag_NoAtime] = GFS2_DIF_NOATIME,
	[iflag_Index] = GFS2_DIF_EXHASH,
	[iflag_JournalData] = GFS2_DIF_JDATA,
	[iflag_DirectIO] = GFS2_DIF_DIRECTIO,
213
214
};

215
216
217
218
219
220
221
222
static const u32 gfs2_to_iflags[32] = {
	[gfs2fl_Sync] = IFLAG_SYNC,
	[gfs2fl_Immutable] = IFLAG_IMMUTABLE,
	[gfs2fl_AppendOnly] = IFLAG_APPEND,
	[gfs2fl_NoAtime] = IFLAG_NOATIME,
	[gfs2fl_ExHash] = IFLAG_INDEX,
	[gfs2fl_Jdata] = IFLAG_JOURNAL_DATA,
	[gfs2fl_Directio] = IFLAG_DIRECTIO,
223
224
	[gfs2fl_InheritDirectio] = IFLAG_DIRECTIO,
	[gfs2fl_InheritJdata] = IFLAG_JOURNAL_DATA,
225
};
226

227
static int gfs2_get_flags(struct file *filp, u32 __user *ptr)
228
{
229
	struct inode *inode = filp->f_dentry->d_inode;
230
	struct gfs2_inode *ip = GFS2_I(inode);
231
232
	struct gfs2_holder gh;
	int error;
233
	u32 iflags;
234
235
236
237
238

	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
	error = gfs2_glock_nq_m_atime(1, &gh);
	if (error)
		return error;
239

240
241
	iflags = iflags_cvt(gfs2_to_iflags, ip->i_di.di_flags);
	if (put_user(iflags, ptr))
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
		error = -EFAULT;

	gfs2_glock_dq_m(1, &gh);
	gfs2_holder_uninit(&gh);
	return error;
}

/* Flags that can be set by user space */
#define GFS2_FLAGS_USER_SET (GFS2_DIF_JDATA|			\
			     GFS2_DIF_DIRECTIO|			\
			     GFS2_DIF_IMMUTABLE|		\
			     GFS2_DIF_APPENDONLY|		\
			     GFS2_DIF_NOATIME|			\
			     GFS2_DIF_SYNC|			\
			     GFS2_DIF_SYSTEM|			\
			     GFS2_DIF_INHERIT_DIRECTIO|		\
			     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
 *
 */
267
static int do_gfs2_set_flags(struct file *filp, u32 reqflags, u32 mask)
268
{
269
	struct inode *inode = filp->f_dentry->d_inode;
270
271
	struct gfs2_inode *ip = GFS2_I(inode);
	struct gfs2_sbd *sdp = GFS2_SB(inode);
272
273
274
	struct buffer_head *bh;
	struct gfs2_holder gh;
	int error;
275
	u32 new_flags, flags;
276
277

	error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
278
	if (error)
279
280
		return error;

281
282
	flags = ip->i_di.di_flags;
	new_flags = (flags & ~mask) | (reqflags & mask);
283
284
285
	if ((new_flags ^ flags) == 0)
		goto out;

286
287
288
289
290
291
292
	if (S_ISDIR(inode->i_mode)) {
		if ((new_flags ^ flags) & GFS2_DIF_JDATA)
			new_flags ^= (GFS2_DIF_JDATA|GFS2_DIF_INHERIT_JDATA);
		if ((new_flags ^ flags) & GFS2_DIF_DIRECTIO)
			new_flags ^= (GFS2_DIF_DIRECTIO|GFS2_DIF_INHERIT_DIRECTIO);
	}

293
294
295
296
297
298
299
300
301
	error = -EINVAL;
	if ((new_flags ^ flags) & ~GFS2_FLAGS_USER_SET)
		goto out;

	error = -EPERM;
	if (IS_IMMUTABLE(inode) && (new_flags & GFS2_DIF_IMMUTABLE))
		goto out;
	if (IS_APPEND(inode) && (new_flags & GFS2_DIF_APPENDONLY))
		goto out;
302
	if (((new_flags ^ flags) & GFS2_DIF_IMMUTABLE) &&
303
	    !capable(CAP_LINUX_IMMUTABLE))
304
		goto out;
305
	if (!IS_IMMUTABLE(inode)) {
306
		error = permission(inode, MAY_WRITE, NULL);
307
308
309
		if (error)
			goto out;
	}
310

311
	error = gfs2_trans_begin(sdp, RES_DINODE, 0);
312
313
	if (error)
		goto out;
314
315
316
	error = gfs2_meta_inode_buffer(ip, &bh);
	if (error)
		goto out_trans_end;
317
318
319
320
	gfs2_trans_add_bh(ip->i_gl, bh, 1);
	ip->i_di.di_flags = new_flags;
	gfs2_dinode_out(&ip->i_di, bh->b_data);
	brelse(bh);
321
322
out_trans_end:
	gfs2_trans_end(sdp);
323
324
325
326
327
out:
	gfs2_glock_dq_uninit(&gh);
	return error;
}

328
static int gfs2_set_flags(struct file *filp, u32 __user *ptr)
329
{
330
331
	u32 iflags, gfsflags;
	if (get_user(iflags, ptr))
332
		return -EFAULT;
333
	gfsflags = iflags_cvt(iflags_to_gfs2, iflags);
334
	return do_gfs2_set_flags(filp, gfsflags, ~0);
335
336
}

337
static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
338
339
{
	switch(cmd) {
340
	case IFLAGS_GET_IOC:
341
		return gfs2_get_flags(filp, (u32 __user *)arg);
342
	case IFLAGS_SET_IOC:
343
		return gfs2_set_flags(filp, (u32 __user *)arg);
344
345
346
347
348
	}
	return -ENOTTY;
}


David Teigland's avatar
David Teigland committed
349
350
351
352
353
354
355
356
357
358
/**
 * gfs2_mmap -
 * @file: The file to map
 * @vma: The VMA which described the mapping
 *
 * Returns: 0 or error code
 */

static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
{
359
	struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
David Teigland's avatar
David Teigland committed
360
361
362
363
364
365
366
367
368
369
	struct gfs2_holder i_gh;
	int error;

	gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &i_gh);
	error = gfs2_glock_nq_atime(&i_gh);
	if (error) {
		gfs2_holder_uninit(&i_gh);
		return error;
	}

370
371
372
373
374
375
376
377
	/* This is VM_MAYWRITE instead of VM_WRITE because a call
	   to mprotect() can turn on VM_WRITE later. */

	if ((vma->vm_flags & (VM_MAYSHARE | VM_MAYWRITE)) ==
	    (VM_MAYSHARE | VM_MAYWRITE))
		vma->vm_ops = &gfs2_vm_ops_sharewrite;
	else
		vma->vm_ops = &gfs2_vm_ops_private;
David Teigland's avatar
David Teigland committed
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393

	gfs2_glock_dq_uninit(&i_gh);

	return error;
}

/**
 * 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)
{
394
	struct gfs2_inode *ip = GFS2_I(inode);
David Teigland's avatar
David Teigland committed
395
396
397
398
399
400
401
402
	struct gfs2_holder i_gh;
	struct gfs2_file *fp;
	int error;

	fp = kzalloc(sizeof(struct gfs2_file), GFP_KERNEL);
	if (!fp)
		return -ENOMEM;

403
	mutex_init(&fp->f_fl_mutex);
David Teigland's avatar
David Teigland committed
404

405
	gfs2_assert_warn(GFS2_SB(inode), !file->private_data);
406
	file->private_data = fp;
David Teigland's avatar
David Teigland committed
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

	if (S_ISREG(ip->i_di.di_mode)) {
		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) &&
		    ip->i_di.di_size > MAX_NON_LFS) {
			error = -EFBIG;
			goto fail_gunlock;
		}

		/* Listen to the Direct I/O flag */

		if (ip->i_di.di_flags & GFS2_DIF_DIRECTIO)
			file->f_flags |= O_DIRECT;

		gfs2_glock_dq_uninit(&i_gh);
	}

	return 0;

430
fail_gunlock:
David Teigland's avatar
David Teigland committed
431
	gfs2_glock_dq_uninit(&i_gh);
432
fail:
433
	file->private_data = NULL;
David Teigland's avatar
David Teigland committed
434
435
436
437
438
439
440
441
442
443
444
445
446
447
	kfree(fp);
	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)
{
448
	struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
David Teigland's avatar
David Teigland committed
449
450
	struct gfs2_file *fp;

451
452
	fp = file->private_data;
	file->private_data = NULL;
David Teigland's avatar
David Teigland committed
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471

	if (gfs2_assert_warn(sdp, fp))
		return -EIO;

	kfree(fp);

	return 0;
}

/**
 * gfs2_fsync - sync the dirty data for a file (across the cluster)
 * @file: the file that points to the dentry (we ignore this)
 * @dentry: the dentry that points to the inode to sync
 *
 * Returns: errno
 */

static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync)
{
472
	struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
David Teigland's avatar
David Teigland committed
473

474
	gfs2_log_flush(ip->i_gl->gl_sbd, ip->i_gl);
David Teigland's avatar
David Teigland committed
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489

	return 0;
}

/**
 * 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)
{
490
491
	struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
	struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
David Teigland's avatar
David Teigland committed
492
493
494
495
496
497
498
499
500
501
502
	struct lm_lockname name =
		{ .ln_number = ip->i_num.no_addr,
		  .ln_type = LM_TYPE_PLOCK };

	if (!(fl->fl_flags & FL_POSIX))
		return -ENOLCK;
	if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
		return -ENOLCK;

	if (sdp->sd_args.ar_localflocks) {
		if (IS_GETLK(cmd)) {
503
504
505
			struct file_lock tmp;
			int ret;
			ret = posix_test_lock(file, fl, &tmp);
David Teigland's avatar
David Teigland committed
506
			fl->fl_type = F_UNLCK;
507
508
			if (ret)
				memcpy(fl, &tmp, sizeof(struct file_lock));
David Teigland's avatar
David Teigland committed
509
510
			return 0;
		} else {
511
			return posix_lock_file_wait(file, fl);
David Teigland's avatar
David Teigland committed
512
513
514
515
516
517
518
519
520
521
522
523
524
		}
	}

	if (IS_GETLK(cmd))
		return gfs2_lm_plock_get(sdp, &name, file, fl);
	else if (fl->fl_type == F_UNLCK)
		return gfs2_lm_punlock(sdp, &name, file, fl);
	else
		return gfs2_lm_plock(sdp, &name, file, cmd, fl);
}

static int do_flock(struct file *file, int cmd, struct file_lock *fl)
{
525
	struct gfs2_file *fp = file->private_data;
David Teigland's avatar
David Teigland committed
526
	struct gfs2_holder *fl_gh = &fp->f_fl_gh;
527
	struct gfs2_inode *ip = GFS2_I(file->f_dentry->d_inode);
David Teigland's avatar
David Teigland committed
528
529
530
531
532
533
	struct gfs2_glock *gl;
	unsigned int state;
	int flags;
	int error = 0;

	state = (fl->fl_type == F_WRLCK) ? LM_ST_EXCLUSIVE : LM_ST_SHARED;
534
	flags = (IS_SETLKW(cmd) ? 0 : LM_FLAG_TRY) | GL_EXACT | GL_NOCACHE;
David Teigland's avatar
David Teigland committed
535

536
	mutex_lock(&fp->f_fl_mutex);
David Teigland's avatar
David Teigland committed
537
538
539
540
541
542
543

	gl = fl_gh->gh_gl;
	if (gl) {
		if (fl_gh->gh_state == state)
			goto out;
		gfs2_glock_hold(gl);
		flock_lock_file_wait(file,
544
				     &(struct file_lock){.fl_type = F_UNLCK});
David Teigland's avatar
David Teigland committed
545
546
		gfs2_glock_dq_uninit(fl_gh);
	} else {
547
		error = gfs2_glock_get(GFS2_SB(&ip->i_inode),
David Teigland's avatar
David Teigland committed
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
				      ip->i_num.no_addr, &gfs2_flock_glops,
				      CREATE, &gl);
		if (error)
			goto out;
	}

	gfs2_holder_init(gl, state, flags, fl_gh);
	gfs2_glock_put(gl);

	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);
564
		gfs2_assert_warn(GFS2_SB(&ip->i_inode), !error);
David Teigland's avatar
David Teigland committed
565
566
	}

567
out:
568
	mutex_unlock(&fp->f_fl_mutex);
David Teigland's avatar
David Teigland committed
569
570
571
572
573
	return error;
}

static void do_unflock(struct file *file, struct file_lock *fl)
{
574
	struct gfs2_file *fp = file->private_data;
David Teigland's avatar
David Teigland committed
575
576
	struct gfs2_holder *fl_gh = &fp->f_fl_gh;

577
	mutex_lock(&fp->f_fl_mutex);
David Teigland's avatar
David Teigland committed
578
579
580
	flock_lock_file_wait(file, fl);
	if (fl_gh->gh_gl)
		gfs2_glock_dq_uninit(fl_gh);
581
	mutex_unlock(&fp->f_fl_mutex);
David Teigland's avatar
David Teigland committed
582
583
584
585
586
587
588
589
590
591
592
593
594
}

/**
 * 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)
{
595
596
	struct gfs2_inode *ip = GFS2_I(file->f_mapping->host);
	struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
David Teigland's avatar
David Teigland committed
597
598
599
600
601
602
603
604
605
606
607
608

	if (!(fl->fl_flags & FL_FLOCK))
		return -ENOLCK;
	if ((ip->i_di.di_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
		return -ENOLCK;

	if (sdp->sd_args.ar_localflocks)
		return flock_lock_file_wait(file, fl);

	if (fl->fl_type == F_UNLCK) {
		do_unflock(file, fl);
		return 0;
609
	} else {
David Teigland's avatar
David Teigland committed
610
		return do_flock(file, cmd, fl);
611
	}
David Teigland's avatar
David Teigland committed
612
613
}

614
const struct file_operations gfs2_file_fops = {
615
	.llseek		= gfs2_llseek,
616
	.read		= do_sync_read,
617
	.aio_read	= generic_file_aio_read,
618
	.write		= do_sync_write,
619
620
621
622
623
624
625
626
627
628
629
	.aio_write	= generic_file_aio_write,
	.unlocked_ioctl	= gfs2_ioctl,
	.mmap		= gfs2_mmap,
	.open		= gfs2_open,
	.release	= gfs2_close,
	.fsync		= gfs2_fsync,
	.lock		= gfs2_lock,
	.sendfile	= generic_file_sendfile,
	.flock		= gfs2_flock,
	.splice_read	= generic_file_splice_read,
	.splice_write	= generic_file_splice_write,
David Teigland's avatar
David Teigland committed
630
631
};

632
const struct file_operations gfs2_dir_fops = {
633
634
635
636
637
638
639
	.readdir	= gfs2_readdir,
	.unlocked_ioctl	= gfs2_ioctl,
	.open		= gfs2_open,
	.release	= gfs2_close,
	.fsync		= gfs2_fsync,
	.lock		= gfs2_lock,
	.flock		= gfs2_flock,
David Teigland's avatar
David Teigland committed
640
641
};