xfs_iops.c 19.7 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
2 3
 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
 * All Rights Reserved.
L
Linus Torvalds 已提交
4
 *
5 6
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
L
Linus Torvalds 已提交
7 8
 * published by the Free Software Foundation.
 *
9 10 11 12
 * This program is distributed in the hope that it would be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
L
Linus Torvalds 已提交
13
 *
14 15 16
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write the Free Software Foundation,
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
L
Linus Torvalds 已提交
17 18 19
 */
#include "xfs.h"
#include "xfs_fs.h"
20
#include "xfs_acl.h"
21
#include "xfs_bit.h"
L
Linus Torvalds 已提交
22
#include "xfs_log.h"
23
#include "xfs_inum.h"
L
Linus Torvalds 已提交
24 25 26 27 28 29 30 31 32
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dir2.h"
#include "xfs_alloc.h"
#include "xfs_dmapi.h"
#include "xfs_quota.h"
#include "xfs_mount.h"
#include "xfs_bmap_btree.h"
33
#include "xfs_alloc_btree.h"
L
Linus Torvalds 已提交
34 35
#include "xfs_ialloc_btree.h"
#include "xfs_dir2_sf.h"
36
#include "xfs_attr_sf.h"
L
Linus Torvalds 已提交
37 38 39
#include "xfs_dinode.h"
#include "xfs_inode.h"
#include "xfs_bmap.h"
40 41
#include "xfs_btree.h"
#include "xfs_ialloc.h"
L
Linus Torvalds 已提交
42 43 44 45 46 47 48
#include "xfs_rtalloc.h"
#include "xfs_error.h"
#include "xfs_itable.h"
#include "xfs_rw.h"
#include "xfs_attr.h"
#include "xfs_buf_item.h"
#include "xfs_utils.h"
49
#include "xfs_vnodeops.h"
C
Christoph Hellwig 已提交
50
#include "xfs_trace.h"
L
Linus Torvalds 已提交
51

52
#include <linux/capability.h>
L
Linus Torvalds 已提交
53 54
#include <linux/xattr.h>
#include <linux/namei.h>
55
#include <linux/posix_acl.h>
56
#include <linux/security.h>
D
David Chinner 已提交
57
#include <linux/falloc.h>
E
Eric Sandeen 已提交
58
#include <linux/fiemap.h>
59
#include <linux/slab.h>
L
Linus Torvalds 已提交
60

61
/*
62 63 64
 * Bring the timestamps in the XFS inode uptodate.
 *
 * Used before writing the inode to disk.
65 66
 */
void
67
xfs_synchronize_times(
68 69
	xfs_inode_t	*ip)
{
70
	struct inode	*inode = VFS_I(ip);
71

72 73 74 75 76 77
	ip->i_d.di_atime.t_sec = (__int32_t)inode->i_atime.tv_sec;
	ip->i_d.di_atime.t_nsec = (__int32_t)inode->i_atime.tv_nsec;
	ip->i_d.di_ctime.t_sec = (__int32_t)inode->i_ctime.tv_sec;
	ip->i_d.di_ctime.t_nsec = (__int32_t)inode->i_ctime.tv_nsec;
	ip->i_d.di_mtime.t_sec = (__int32_t)inode->i_mtime.tv_sec;
	ip->i_d.di_mtime.t_nsec = (__int32_t)inode->i_mtime.tv_nsec;
78 79
}

80
/*
81
 * If the linux inode is valid, mark it dirty.
82 83 84 85 86 87 88
 * Used when commiting a dirty inode into a transaction so that
 * the inode will get written back by the linux code
 */
void
xfs_mark_inode_dirty_sync(
	xfs_inode_t	*ip)
{
89
	struct inode	*inode = VFS_I(ip);
90

91
	if (!(inode->i_state & (I_WILL_FREE|I_FREEING|I_CLEAR)))
92
		mark_inode_dirty_sync(inode);
93 94
}

95 96 97 98 99 100 101 102 103 104
void
xfs_mark_inode_dirty(
	xfs_inode_t	*ip)
{
	struct inode	*inode = VFS_I(ip);

	if (!(inode->i_state & (I_WILL_FREE|I_FREEING|I_CLEAR)))
		mark_inode_dirty(inode);
}

105 106 107 108 109 110 111 112 113 114
/*
 * Change the requested timestamp in the given inode.
 * We don't lock across timestamp updates, and we don't log them but
 * we do record the fact that there is dirty information in core.
 */
void
xfs_ichgtime(
	xfs_inode_t	*ip,
	int		flags)
{
115
	struct inode	*inode = VFS_I(ip);
116
	timespec_t	tv;
C
Christoph Hellwig 已提交
117
	int		sync_it = 0;
118

C
Christoph Hellwig 已提交
119 120 121 122
	tv = current_fs_time(inode->i_sb);

	if ((flags & XFS_ICHGTIME_MOD) &&
	    !timespec_equal(&inode->i_mtime, &tv)) {
123
		inode->i_mtime = tv;
C
Christoph Hellwig 已提交
124
		sync_it = 1;
125
	}
C
Christoph Hellwig 已提交
126 127
	if ((flags & XFS_ICHGTIME_CHG) &&
	    !timespec_equal(&inode->i_ctime, &tv)) {
128
		inode->i_ctime = tv;
C
Christoph Hellwig 已提交
129
		sync_it = 1;
130 131 132
	}

	/*
133 134
	 * Update complete - now make sure everyone knows that the inode
	 * is dirty.
135
	 */
136
	if (sync_it)
137
		xfs_mark_inode_dirty_sync(ip);
138 139
}

140 141 142 143 144 145 146
/*
 * Hook in SELinux.  This is not quite correct yet, what we really need
 * here (as we do for default ACLs) is a mechanism by which creation of
 * these attrs can be journalled at inode creation time (along with the
 * inode, of course, such that log replay can't cause these to be lost).
 */
STATIC int
147
xfs_init_security(
148
	struct inode	*inode,
149 150
	struct inode	*dir)
{
151
	struct xfs_inode *ip = XFS_I(inode);
152 153
	size_t		length;
	void		*value;
154
	unsigned char	*name;
155 156
	int		error;

157
	error = security_inode_init_security(inode, dir, (char **)&name,
158
					     &value, &length);
159 160 161 162 163 164
	if (error) {
		if (error == -EOPNOTSUPP)
			return 0;
		return -error;
	}

165
	error = xfs_attr_set(ip, name, value, length, ATTR_SECURE);
166 167 168 169 170 171

	kfree(name);
	kfree(value);
	return error;
}

172 173 174 175 176 177 178 179 180
static void
xfs_dentry_to_name(
	struct xfs_name	*namep,
	struct dentry	*dentry)
{
	namep->name = dentry->d_name.name;
	namep->len = dentry->d_name.len;
}

181
STATIC void
182
xfs_cleanup_inode(
183
	struct inode	*dir,
184
	struct inode	*inode,
185
	struct dentry	*dentry)
186
{
187
	struct xfs_name	teardown;
188 189

	/* Oh, the horror.
190
	 * If we can't add the ACL or we fail in
191
	 * xfs_init_security we must back out.
192 193
	 * ENOSPC can hit here, among other things.
	 */
194
	xfs_dentry_to_name(&teardown, dentry);
195

196
	xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
197
	iput(inode);
198 199
}

L
Linus Torvalds 已提交
200
STATIC int
201
xfs_vn_mknod(
L
Linus Torvalds 已提交
202 203 204 205 206
	struct inode	*dir,
	struct dentry	*dentry,
	int		mode,
	dev_t		rdev)
{
C
Christoph Hellwig 已提交
207
	struct inode	*inode;
208
	struct xfs_inode *ip = NULL;
209
	struct posix_acl *default_acl = NULL;
210
	struct xfs_name	name;
L
Linus Torvalds 已提交
211 212 213 214 215 216
	int		error;

	/*
	 * Irix uses Missed'em'V split, but doesn't want to see
	 * the upper 5 bits of (14bit) major.
	 */
217 218 219 220 221 222 223
	if (S_ISCHR(mode) || S_ISBLK(mode)) {
		if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff))
			return -EINVAL;
		rdev = sysv_encode_dev(rdev);
	} else {
		rdev = 0;
	}
L
Linus Torvalds 已提交
224

225 226 227 228
	if (IS_POSIXACL(dir)) {
		default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT);
		if (IS_ERR(default_acl))
			return -PTR_ERR(default_acl);
L
Linus Torvalds 已提交
229

230 231
		if (!default_acl)
			mode &= ~current_umask();
232
	}
L
Linus Torvalds 已提交
233

234 235
	xfs_dentry_to_name(&name, dentry);
	error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL);
C
Christoph Hellwig 已提交
236 237
	if (unlikely(error))
		goto out_free_acl;
238

239
	inode = VFS_I(ip);
240 241

	error = xfs_init_security(inode, dir);
C
Christoph Hellwig 已提交
242 243 244 245
	if (unlikely(error))
		goto out_cleanup_inode;

	if (default_acl) {
246
		error = -xfs_inherit_acl(inode, default_acl);
C
Christoph Hellwig 已提交
247 248
		if (unlikely(error))
			goto out_cleanup_inode;
249
		posix_acl_release(default_acl);
L
Linus Torvalds 已提交
250 251 252
	}


C
Christoph Hellwig 已提交
253 254 255 256
	d_instantiate(dentry, inode);
	return -error;

 out_cleanup_inode:
257
	xfs_cleanup_inode(dir, inode, dentry);
C
Christoph Hellwig 已提交
258
 out_free_acl:
259
	posix_acl_release(default_acl);
L
Linus Torvalds 已提交
260 261 262 263
	return -error;
}

STATIC int
264
xfs_vn_create(
L
Linus Torvalds 已提交
265 266 267 268 269
	struct inode	*dir,
	struct dentry	*dentry,
	int		mode,
	struct nameidata *nd)
{
270
	return xfs_vn_mknod(dir, dentry, mode, 0);
L
Linus Torvalds 已提交
271 272 273
}

STATIC int
274
xfs_vn_mkdir(
L
Linus Torvalds 已提交
275 276 277 278
	struct inode	*dir,
	struct dentry	*dentry,
	int		mode)
{
279
	return xfs_vn_mknod(dir, dentry, mode|S_IFDIR, 0);
L
Linus Torvalds 已提交
280 281 282
}

STATIC struct dentry *
283
xfs_vn_lookup(
L
Linus Torvalds 已提交
284 285 286 287
	struct inode	*dir,
	struct dentry	*dentry,
	struct nameidata *nd)
{
288
	struct xfs_inode *cip;
289
	struct xfs_name	name;
L
Linus Torvalds 已提交
290 291 292 293 294
	int		error;

	if (dentry->d_name.len >= MAXNAMELEN)
		return ERR_PTR(-ENAMETOOLONG);

295
	xfs_dentry_to_name(&name, dentry);
296
	error = xfs_lookup(XFS_I(dir), &name, &cip, NULL);
297
	if (unlikely(error)) {
L
Linus Torvalds 已提交
298 299 300 301 302 303
		if (unlikely(error != ENOENT))
			return ERR_PTR(-error);
		d_add(dentry, NULL);
		return NULL;
	}

304
	return d_splice_alias(VFS_I(cip), dentry);
L
Linus Torvalds 已提交
305 306
}

307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
STATIC struct dentry *
xfs_vn_ci_lookup(
	struct inode	*dir,
	struct dentry	*dentry,
	struct nameidata *nd)
{
	struct xfs_inode *ip;
	struct xfs_name	xname;
	struct xfs_name ci_name;
	struct qstr	dname;
	int		error;

	if (dentry->d_name.len >= MAXNAMELEN)
		return ERR_PTR(-ENAMETOOLONG);

	xfs_dentry_to_name(&xname, dentry);
	error = xfs_lookup(XFS_I(dir), &xname, &ip, &ci_name);
	if (unlikely(error)) {
		if (unlikely(error != ENOENT))
			return ERR_PTR(-error);
327 328 329 330 331
		/*
		 * call d_add(dentry, NULL) here when d_drop_negative_children
		 * is called in xfs_vn_mknod (ie. allow negative dentries
		 * with CI filesystems).
		 */
332 333 334 335 336
		return NULL;
	}

	/* if exact match, just splice and exit */
	if (!ci_name.name)
337
		return d_splice_alias(VFS_I(ip), dentry);
338 339 340 341

	/* else case-insensitive match... */
	dname.name = ci_name.name;
	dname.len = ci_name.len;
342
	dentry = d_add_ci(dentry, VFS_I(ip), &dname);
343 344 345 346
	kmem_free(ci_name.name);
	return dentry;
}

L
Linus Torvalds 已提交
347
STATIC int
348
xfs_vn_link(
L
Linus Torvalds 已提交
349 350 351 352
	struct dentry	*old_dentry,
	struct inode	*dir,
	struct dentry	*dentry)
{
353
	struct inode	*inode = old_dentry->d_inode;
354
	struct xfs_name	name;
L
Linus Torvalds 已提交
355 356
	int		error;

357
	xfs_dentry_to_name(&name, dentry);
L
Linus Torvalds 已提交
358

359
	error = xfs_link(XFS_I(dir), XFS_I(inode), &name);
360
	if (unlikely(error))
361 362
		return -error;

363
	atomic_inc(&inode->i_count);
364 365
	d_instantiate(dentry, inode);
	return 0;
L
Linus Torvalds 已提交
366 367 368
}

STATIC int
369
xfs_vn_unlink(
L
Linus Torvalds 已提交
370 371 372
	struct inode	*dir,
	struct dentry	*dentry)
{
373
	struct xfs_name	name;
L
Linus Torvalds 已提交
374 375
	int		error;

376
	xfs_dentry_to_name(&name, dentry);
L
Linus Torvalds 已提交
377

378 379 380 381 382 383 384 385 386 387 388 389
	error = -xfs_remove(XFS_I(dir), &name, XFS_I(dentry->d_inode));
	if (error)
		return error;

	/*
	 * With unlink, the VFS makes the dentry "negative": no inode,
	 * but still hashed. This is incompatible with case-insensitive
	 * mode, so invalidate (unhash) the dentry in CI-mode.
	 */
	if (xfs_sb_version_hasasciici(&XFS_M(dir->i_sb)->m_sb))
		d_invalidate(dentry);
	return 0;
L
Linus Torvalds 已提交
390 391 392
}

STATIC int
393
xfs_vn_symlink(
L
Linus Torvalds 已提交
394 395 396 397
	struct inode	*dir,
	struct dentry	*dentry,
	const char	*symname)
{
398 399
	struct inode	*inode;
	struct xfs_inode *cip = NULL;
400
	struct xfs_name	name;
L
Linus Torvalds 已提交
401
	int		error;
402
	mode_t		mode;
L
Linus Torvalds 已提交
403

404
	mode = S_IFLNK |
A
Al Viro 已提交
405
		(irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO);
406
	xfs_dentry_to_name(&name, dentry);
L
Linus Torvalds 已提交
407

408
	error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL);
409 410 411
	if (unlikely(error))
		goto out;

412
	inode = VFS_I(cip);
413 414 415 416 417 418 419 420 421

	error = xfs_init_security(inode, dir);
	if (unlikely(error))
		goto out_cleanup_inode;

	d_instantiate(dentry, inode);
	return 0;

 out_cleanup_inode:
422
	xfs_cleanup_inode(dir, inode, dentry);
423
 out:
L
Linus Torvalds 已提交
424 425 426 427
	return -error;
}

STATIC int
428
xfs_vn_rename(
L
Linus Torvalds 已提交
429 430 431 432 433 434
	struct inode	*odir,
	struct dentry	*odentry,
	struct inode	*ndir,
	struct dentry	*ndentry)
{
	struct inode	*new_inode = ndentry->d_inode;
435 436
	struct xfs_name	oname;
	struct xfs_name	nname;
L
Linus Torvalds 已提交
437

438 439 440
	xfs_dentry_to_name(&oname, odentry);
	xfs_dentry_to_name(&nname, ndentry);

441
	return -xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode),
442 443
			   XFS_I(ndir), &nname, new_inode ?
			   			XFS_I(new_inode) : NULL);
L
Linus Torvalds 已提交
444 445 446 447 448 449 450
}

/*
 * careful here - this function can get called recursively, so
 * we need to be very careful about how much stack we use.
 * uio is kmalloced for this reason...
 */
451
STATIC void *
452
xfs_vn_follow_link(
L
Linus Torvalds 已提交
453 454 455 456
	struct dentry		*dentry,
	struct nameidata	*nd)
{
	char			*link;
457
	int			error = -ENOMEM;
L
Linus Torvalds 已提交
458

459
	link = kmalloc(MAXPATHLEN+1, GFP_KERNEL);
460 461
	if (!link)
		goto out_err;
L
Linus Torvalds 已提交
462

463
	error = -xfs_readlink(XFS_I(dentry->d_inode), link);
464 465
	if (unlikely(error))
		goto out_kfree;
L
Linus Torvalds 已提交
466 467

	nd_set_link(nd, link);
468
	return NULL;
469 470 471 472 473 474

 out_kfree:
	kfree(link);
 out_err:
	nd_set_link(nd, ERR_PTR(error));
	return NULL;
L
Linus Torvalds 已提交
475 476
}

477
STATIC void
478
xfs_vn_put_link(
479 480 481
	struct dentry	*dentry,
	struct nameidata *nd,
	void		*p)
L
Linus Torvalds 已提交
482
{
483 484
	char		*s = nd_get_link(nd);

L
Linus Torvalds 已提交
485 486 487 488 489
	if (!IS_ERR(s))
		kfree(s);
}

STATIC int
490
xfs_vn_getattr(
491 492 493
	struct vfsmount		*mnt,
	struct dentry		*dentry,
	struct kstat		*stat)
L
Linus Torvalds 已提交
494
{
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
	struct inode		*inode = dentry->d_inode;
	struct xfs_inode	*ip = XFS_I(inode);
	struct xfs_mount	*mp = ip->i_mount;

	xfs_itrace_entry(ip);

	if (XFS_FORCED_SHUTDOWN(mp))
		return XFS_ERROR(EIO);

	stat->size = XFS_ISIZE(ip);
	stat->dev = inode->i_sb->s_dev;
	stat->mode = ip->i_d.di_mode;
	stat->nlink = ip->i_d.di_nlink;
	stat->uid = ip->i_d.di_uid;
	stat->gid = ip->i_d.di_gid;
	stat->ino = ip->i_ino;
	stat->atime = inode->i_atime;
512 513
	stat->mtime = inode->i_mtime;
	stat->ctime = inode->i_ctime;
514 515 516 517 518 519 520 521 522 523 524 525
	stat->blocks =
		XFS_FSB_TO_BB(mp, ip->i_d.di_nblocks + ip->i_delayed_blks);


	switch (inode->i_mode & S_IFMT) {
	case S_IFBLK:
	case S_IFCHR:
		stat->blksize = BLKDEV_IOSIZE;
		stat->rdev = MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff,
				   sysv_minor(ip->i_df.if_u2.if_rdev));
		break;
	default:
526
		if (XFS_IS_REALTIME_INODE(ip)) {
527 528 529 530 531 532 533 534 535 536 537
			/*
			 * If the file blocks are being allocated from a
			 * realtime volume, then return the inode's realtime
			 * extent size or the realtime volume's extent size.
			 */
			stat->blksize =
				xfs_get_extsz_hint(ip) << mp->m_sb.sb_blocklog;
		} else
			stat->blksize = xfs_preferred_iosize(mp);
		stat->rdev = 0;
		break;
538
	}
539 540

	return 0;
L
Linus Torvalds 已提交
541 542 543
}

STATIC int
544
xfs_vn_setattr(
L
Linus Torvalds 已提交
545
	struct dentry	*dentry,
546
	struct iattr	*iattr)
L
Linus Torvalds 已提交
547
{
C
Christoph Hellwig 已提交
548
	return -xfs_setattr(XFS_I(dentry->d_inode), iattr, 0);
L
Linus Torvalds 已提交
549 550
}

551 552 553 554 555
/*
 * block_truncate_page can return an error, but we can't propagate it
 * at all here. Leave a complaint + stack trace in the syslog because
 * this could be bad. If it is bad, we need to propagate the error further.
 */
L
Linus Torvalds 已提交
556
STATIC void
557
xfs_vn_truncate(
L
Linus Torvalds 已提交
558 559
	struct inode	*inode)
{
560 561 562 563
	int	error;
	error = block_truncate_page(inode->i_mapping, inode->i_size,
							xfs_get_blocks);
	WARN_ON(error);
L
Linus Torvalds 已提交
564 565
}

D
David Chinner 已提交
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587
STATIC long
xfs_vn_fallocate(
	struct inode	*inode,
	int		mode,
	loff_t		offset,
	loff_t		len)
{
	long		error;
	loff_t		new_size = 0;
	xfs_flock64_t	bf;
	xfs_inode_t	*ip = XFS_I(inode);

	/* preallocation on directories not yet supported */
	error = -ENODEV;
	if (S_ISDIR(inode->i_mode))
		goto out_error;

	bf.l_whence = 0;
	bf.l_start = offset;
	bf.l_len = len;

	xfs_ilock(ip, XFS_IOLOCK_EXCL);
588 589
	error = -xfs_change_file_space(ip, XFS_IOC_RESVSP, &bf,
				       0, XFS_ATTR_NOLOCK);
D
David Chinner 已提交
590 591 592 593 594 595
	if (!error && !(mode & FALLOC_FL_KEEP_SIZE) &&
	    offset + len > i_size_read(inode))
		new_size = offset + len;

	/* Change file size if needed */
	if (new_size) {
596
		struct iattr iattr;
D
David Chinner 已提交
597

598 599
		iattr.ia_valid = ATTR_SIZE;
		iattr.ia_size = new_size;
600
		error = -xfs_setattr(ip, &iattr, XFS_ATTR_NOLOCK);
D
David Chinner 已提交
601 602 603 604 605 606
	}

	xfs_iunlock(ip, XFS_IOLOCK_EXCL);
out_error:
	return error;
}
L
Linus Torvalds 已提交
607

E
Eric Sandeen 已提交
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 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
#define XFS_FIEMAP_FLAGS	(FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR)

/*
 * Call fiemap helper to fill in user data.
 * Returns positive errors to xfs_getbmap.
 */
STATIC int
xfs_fiemap_format(
	void			**arg,
	struct getbmapx		*bmv,
	int			*full)
{
	int			error;
	struct fiemap_extent_info *fieinfo = *arg;
	u32			fiemap_flags = 0;
	u64			logical, physical, length;

	/* Do nothing for a hole */
	if (bmv->bmv_block == -1LL)
		return 0;

	logical = BBTOB(bmv->bmv_offset);
	physical = BBTOB(bmv->bmv_block);
	length = BBTOB(bmv->bmv_length);

	if (bmv->bmv_oflags & BMV_OF_PREALLOC)
		fiemap_flags |= FIEMAP_EXTENT_UNWRITTEN;
	else if (bmv->bmv_oflags & BMV_OF_DELALLOC) {
		fiemap_flags |= FIEMAP_EXTENT_DELALLOC;
		physical = 0;   /* no block yet */
	}
	if (bmv->bmv_oflags & BMV_OF_LAST)
		fiemap_flags |= FIEMAP_EXTENT_LAST;

	error = fiemap_fill_next_extent(fieinfo, logical, physical,
					length, fiemap_flags);
	if (error > 0) {
		error = 0;
		*full = 1;	/* user array now full */
	}

	return -error;
}

STATIC int
xfs_vn_fiemap(
	struct inode		*inode,
	struct fiemap_extent_info *fieinfo,
	u64			start,
	u64			length)
{
	xfs_inode_t		*ip = XFS_I(inode);
	struct getbmapx		bm;
	int			error;

	error = fiemap_check_flags(fieinfo, XFS_FIEMAP_FLAGS);
	if (error)
		return error;

	/* Set up bmap header for xfs internal routine */
	bm.bmv_offset = BTOBB(start);
	/* Special case for whole file */
	if (length == FIEMAP_MAX_OFFSET)
		bm.bmv_length = -1LL;
	else
		bm.bmv_length = BTOBB(length);

675
	/* We add one because in getbmap world count includes the header */
T
Tao Ma 已提交
676 677 678 679
	bm.bmv_count = !fieinfo->fi_extents_max ? MAXEXTNUM :
					fieinfo->fi_extents_max + 1;
	bm.bmv_count = min_t(__s32, bm.bmv_count,
			     (PAGE_SIZE * 16 / sizeof(struct getbmapx)));
E
Eric Sandeen 已提交
680 681 682 683 684 685 686 687 688 689 690 691 692
	bm.bmv_iflags = BMV_IF_PREALLOC;
	if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR)
		bm.bmv_iflags |= BMV_IF_ATTRFORK;
	if (!(fieinfo->fi_flags & FIEMAP_FLAG_SYNC))
		bm.bmv_iflags |= BMV_IF_DELALLOC;

	error = xfs_getbmap(ip, &bm, xfs_fiemap_format, fieinfo);
	if (error)
		return -error;

	return 0;
}

693
static const struct inode_operations xfs_inode_operations = {
694
	.check_acl		= xfs_check_acl,
695 696 697
	.truncate		= xfs_vn_truncate,
	.getattr		= xfs_vn_getattr,
	.setattr		= xfs_vn_setattr,
698 699 700
	.setxattr		= generic_setxattr,
	.getxattr		= generic_getxattr,
	.removexattr		= generic_removexattr,
701
	.listxattr		= xfs_vn_listxattr,
D
David Chinner 已提交
702
	.fallocate		= xfs_vn_fallocate,
E
Eric Sandeen 已提交
703
	.fiemap			= xfs_vn_fiemap,
L
Linus Torvalds 已提交
704 705
};

706
static const struct inode_operations xfs_dir_inode_operations = {
707 708 709 710 711 712
	.create			= xfs_vn_create,
	.lookup			= xfs_vn_lookup,
	.link			= xfs_vn_link,
	.unlink			= xfs_vn_unlink,
	.symlink		= xfs_vn_symlink,
	.mkdir			= xfs_vn_mkdir,
713 714 715 716 717 718 719
	/*
	 * Yes, XFS uses the same method for rmdir and unlink.
	 *
	 * There are some subtile differences deeper in the code,
	 * but we use S_ISDIR to check for those.
	 */
	.rmdir			= xfs_vn_unlink,
720 721
	.mknod			= xfs_vn_mknod,
	.rename			= xfs_vn_rename,
722
	.check_acl		= xfs_check_acl,
723 724
	.getattr		= xfs_vn_getattr,
	.setattr		= xfs_vn_setattr,
725 726 727
	.setxattr		= generic_setxattr,
	.getxattr		= generic_getxattr,
	.removexattr		= generic_removexattr,
728
	.listxattr		= xfs_vn_listxattr,
L
Linus Torvalds 已提交
729 730
};

731
static const struct inode_operations xfs_dir_ci_inode_operations = {
732 733 734 735 736 737
	.create			= xfs_vn_create,
	.lookup			= xfs_vn_ci_lookup,
	.link			= xfs_vn_link,
	.unlink			= xfs_vn_unlink,
	.symlink		= xfs_vn_symlink,
	.mkdir			= xfs_vn_mkdir,
738 739 740 741 742 743 744
	/*
	 * Yes, XFS uses the same method for rmdir and unlink.
	 *
	 * There are some subtile differences deeper in the code,
	 * but we use S_ISDIR to check for those.
	 */
	.rmdir			= xfs_vn_unlink,
745 746
	.mknod			= xfs_vn_mknod,
	.rename			= xfs_vn_rename,
747
	.check_acl		= xfs_check_acl,
748 749
	.getattr		= xfs_vn_getattr,
	.setattr		= xfs_vn_setattr,
750 751 752
	.setxattr		= generic_setxattr,
	.getxattr		= generic_getxattr,
	.removexattr		= generic_removexattr,
753 754 755
	.listxattr		= xfs_vn_listxattr,
};

756
static const struct inode_operations xfs_symlink_inode_operations = {
L
Linus Torvalds 已提交
757
	.readlink		= generic_readlink,
758 759
	.follow_link		= xfs_vn_follow_link,
	.put_link		= xfs_vn_put_link,
760
	.check_acl		= xfs_check_acl,
761 762
	.getattr		= xfs_vn_getattr,
	.setattr		= xfs_vn_setattr,
763 764 765
	.setxattr		= generic_setxattr,
	.getxattr		= generic_getxattr,
	.removexattr		= generic_removexattr,
766
	.listxattr		= xfs_vn_listxattr,
L
Linus Torvalds 已提交
767
};
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798

STATIC void
xfs_diflags_to_iflags(
	struct inode		*inode,
	struct xfs_inode	*ip)
{
	if (ip->i_d.di_flags & XFS_DIFLAG_IMMUTABLE)
		inode->i_flags |= S_IMMUTABLE;
	else
		inode->i_flags &= ~S_IMMUTABLE;
	if (ip->i_d.di_flags & XFS_DIFLAG_APPEND)
		inode->i_flags |= S_APPEND;
	else
		inode->i_flags &= ~S_APPEND;
	if (ip->i_d.di_flags & XFS_DIFLAG_SYNC)
		inode->i_flags |= S_SYNC;
	else
		inode->i_flags &= ~S_SYNC;
	if (ip->i_d.di_flags & XFS_DIFLAG_NOATIME)
		inode->i_flags |= S_NOATIME;
	else
		inode->i_flags &= ~S_NOATIME;
}

/*
 * Initialize the Linux inode, set up the operation vectors and
 * unlock the inode.
 *
 * When reading existing inodes from disk this is called directly
 * from xfs_iget, when creating a new inode it is called from
 * xfs_ialloc after setting up the inode.
799 800 801 802
 *
 * We are always called with an uninitialised linux inode here.
 * We need to initialise the necessary fields and take a reference
 * on it.
803 804 805 806 807
 */
void
xfs_setup_inode(
	struct xfs_inode	*ip)
{
808 809 810
	struct inode		*inode = &ip->i_vnode;

	inode->i_ino = ip->i_ino;
C
Christoph Hellwig 已提交
811
	inode->i_state = I_NEW;
812
	inode_add_to_lists(ip->i_mount->m_super, inode);
813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869

	inode->i_mode	= ip->i_d.di_mode;
	inode->i_nlink	= ip->i_d.di_nlink;
	inode->i_uid	= ip->i_d.di_uid;
	inode->i_gid	= ip->i_d.di_gid;

	switch (inode->i_mode & S_IFMT) {
	case S_IFBLK:
	case S_IFCHR:
		inode->i_rdev =
			MKDEV(sysv_major(ip->i_df.if_u2.if_rdev) & 0x1ff,
			      sysv_minor(ip->i_df.if_u2.if_rdev));
		break;
	default:
		inode->i_rdev = 0;
		break;
	}

	inode->i_generation = ip->i_d.di_gen;
	i_size_write(inode, ip->i_d.di_size);
	inode->i_atime.tv_sec	= ip->i_d.di_atime.t_sec;
	inode->i_atime.tv_nsec	= ip->i_d.di_atime.t_nsec;
	inode->i_mtime.tv_sec	= ip->i_d.di_mtime.t_sec;
	inode->i_mtime.tv_nsec	= ip->i_d.di_mtime.t_nsec;
	inode->i_ctime.tv_sec	= ip->i_d.di_ctime.t_sec;
	inode->i_ctime.tv_nsec	= ip->i_d.di_ctime.t_nsec;
	xfs_diflags_to_iflags(inode, ip);

	switch (inode->i_mode & S_IFMT) {
	case S_IFREG:
		inode->i_op = &xfs_inode_operations;
		inode->i_fop = &xfs_file_operations;
		inode->i_mapping->a_ops = &xfs_address_space_operations;
		break;
	case S_IFDIR:
		if (xfs_sb_version_hasasciici(&XFS_M(inode->i_sb)->m_sb))
			inode->i_op = &xfs_dir_ci_inode_operations;
		else
			inode->i_op = &xfs_dir_inode_operations;
		inode->i_fop = &xfs_dir_file_operations;
		break;
	case S_IFLNK:
		inode->i_op = &xfs_symlink_inode_operations;
		if (!(ip->i_df.if_flags & XFS_IFINLINE))
			inode->i_mapping->a_ops = &xfs_address_space_operations;
		break;
	default:
		inode->i_op = &xfs_inode_operations;
		init_special_inode(inode, inode->i_mode, inode->i_rdev);
		break;
	}

	xfs_iflags_clear(ip, XFS_INEW);
	barrier();

	unlock_new_inode(inode);
}