diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/autofs4/root.c | 12 | ||||
| -rw-r--r-- | fs/cifs/Kconfig | 8 | ||||
| -rw-r--r-- | fs/cifs/cifsacl.c | 48 | ||||
| -rw-r--r-- | fs/cifs/cifsfs.c | 2 | ||||
| -rw-r--r-- | fs/cifs/cifsproto.h | 6 | ||||
| -rw-r--r-- | fs/cifs/connect.c | 5 | ||||
| -rw-r--r-- | fs/cifs/dns_resolve.c | 2 | ||||
| -rw-r--r-- | fs/cifs/file.c | 4 | ||||
| -rw-r--r-- | fs/cifs/fscache.c | 12 | ||||
| -rw-r--r-- | fs/cifs/inode.c | 36 | ||||
| -rw-r--r-- | fs/cifs/readdir.c | 29 | ||||
| -rw-r--r-- | fs/cifs/xattr.c | 55 | ||||
| -rw-r--r-- | fs/compat.c | 28 | ||||
| -rw-r--r-- | fs/exec.c | 36 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 6 | ||||
| -rw-r--r-- | fs/ocfs2/cluster/heartbeat.c | 14 | ||||
| -rw-r--r-- | fs/ocfs2/dcache.c | 1 | ||||
| -rw-r--r-- | fs/ocfs2/dlm/dlmdomain.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2.h | 6 | ||||
| -rw-r--r-- | fs/ocfs2/stack_user.c | 2 | ||||
| -rw-r--r-- | fs/proc/base.c | 2 | ||||
| -rw-r--r-- | fs/reiserfs/xattr_acl.c | 6 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 94 | ||||
| -rw-r--r-- | fs/xfs/linux-2.6/xfs_buf.c | 35 | ||||
| -rw-r--r-- | fs/xfs/xfs_bmap.c | 85 | ||||
| -rw-r--r-- | fs/xfs/xfs_bmap.h | 5 | ||||
| -rw-r--r-- | fs/xfs/xfs_dfrag.c | 13 | ||||
| -rw-r--r-- | fs/xfs/xfs_error.c | 3 | ||||
| -rw-r--r-- | fs/xfs/xfs_error.h | 5 | ||||
| -rw-r--r-- | fs/xfs/xfs_inode_item.c | 31 |
30 files changed, 384 insertions, 209 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index d5c1401f0031..d34896cfb19f 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
| @@ -980,19 +980,11 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp, | |||
| 980 | } | 980 | } |
| 981 | } | 981 | } |
| 982 | 982 | ||
| 983 | static DEFINE_MUTEX(autofs4_ioctl_mutex); | ||
| 984 | |||
| 985 | static long autofs4_root_ioctl(struct file *filp, | 983 | static long autofs4_root_ioctl(struct file *filp, |
| 986 | unsigned int cmd, unsigned long arg) | 984 | unsigned int cmd, unsigned long arg) |
| 987 | { | 985 | { |
| 988 | long ret; | ||
| 989 | struct inode *inode = filp->f_dentry->d_inode; | 986 | struct inode *inode = filp->f_dentry->d_inode; |
| 990 | 987 | return autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | |
| 991 | mutex_lock(&autofs4_ioctl_mutex); | ||
| 992 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | ||
| 993 | mutex_unlock(&autofs4_ioctl_mutex); | ||
| 994 | |||
| 995 | return ret; | ||
| 996 | } | 988 | } |
| 997 | 989 | ||
| 998 | #ifdef CONFIG_COMPAT | 990 | #ifdef CONFIG_COMPAT |
| @@ -1002,13 +994,11 @@ static long autofs4_root_compat_ioctl(struct file *filp, | |||
| 1002 | struct inode *inode = filp->f_path.dentry->d_inode; | 994 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 1003 | int ret; | 995 | int ret; |
| 1004 | 996 | ||
| 1005 | mutex_lock(&autofs4_ioctl_mutex); | ||
| 1006 | if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) | 997 | if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) |
| 1007 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | 998 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); |
| 1008 | else | 999 | else |
| 1009 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, | 1000 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, |
| 1010 | (unsigned long)compat_ptr(arg)); | 1001 | (unsigned long)compat_ptr(arg)); |
| 1011 | mutex_unlock(&autofs4_ioctl_mutex); | ||
| 1012 | 1002 | ||
| 1013 | return ret; | 1003 | return ret; |
| 1014 | } | 1004 | } |
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0ed213970ced..ee45648b0d1a 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
| @@ -4,6 +4,7 @@ config CIFS | |||
| 4 | select NLS | 4 | select NLS |
| 5 | select CRYPTO | 5 | select CRYPTO |
| 6 | select CRYPTO_MD5 | 6 | select CRYPTO_MD5 |
| 7 | select CRYPTO_HMAC | ||
| 7 | select CRYPTO_ARC4 | 8 | select CRYPTO_ARC4 |
| 8 | help | 9 | help |
| 9 | This is the client VFS module for the Common Internet File System | 10 | This is the client VFS module for the Common Internet File System |
| @@ -143,6 +144,13 @@ config CIFS_FSCACHE | |||
| 143 | to be cached locally on disk through the general filesystem cache | 144 | to be cached locally on disk through the general filesystem cache |
| 144 | manager. If unsure, say N. | 145 | manager. If unsure, say N. |
| 145 | 146 | ||
| 147 | config CIFS_ACL | ||
| 148 | bool "Provide CIFS ACL support (EXPERIMENTAL)" | ||
| 149 | depends on EXPERIMENTAL && CIFS_XATTR | ||
| 150 | help | ||
| 151 | Allows to fetch CIFS/NTFS ACL from the server. The DACL blob | ||
| 152 | is handed over to the application/caller. | ||
| 153 | |||
| 146 | config CIFS_EXPERIMENTAL | 154 | config CIFS_EXPERIMENTAL |
| 147 | bool "CIFS Experimental Features (EXPERIMENTAL)" | 155 | bool "CIFS Experimental Features (EXPERIMENTAL)" |
| 148 | depends on CIFS && EXPERIMENTAL | 156 | depends on CIFS && EXPERIMENTAL |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index c9b4792ae825..c6ebea088ac7 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
| @@ -560,7 +560,7 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, | |||
| 560 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 560 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
| 561 | 561 | ||
| 562 | if (IS_ERR(tlink)) | 562 | if (IS_ERR(tlink)) |
| 563 | return NULL; | 563 | return ERR_CAST(tlink); |
| 564 | 564 | ||
| 565 | xid = GetXid(); | 565 | xid = GetXid(); |
| 566 | rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); | 566 | rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); |
| @@ -568,7 +568,9 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, | |||
| 568 | 568 | ||
| 569 | cifs_put_tlink(tlink); | 569 | cifs_put_tlink(tlink); |
| 570 | 570 | ||
| 571 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); | 571 | cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); |
| 572 | if (rc) | ||
| 573 | return ERR_PTR(rc); | ||
| 572 | return pntsd; | 574 | return pntsd; |
| 573 | } | 575 | } |
| 574 | 576 | ||
| @@ -583,7 +585,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
| 583 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 585 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
| 584 | 586 | ||
| 585 | if (IS_ERR(tlink)) | 587 | if (IS_ERR(tlink)) |
| 586 | return NULL; | 588 | return ERR_CAST(tlink); |
| 587 | 589 | ||
| 588 | tcon = tlink_tcon(tlink); | 590 | tcon = tlink_tcon(tlink); |
| 589 | xid = GetXid(); | 591 | xid = GetXid(); |
| @@ -591,23 +593,22 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
| 591 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0, | 593 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0, |
| 592 | &fid, &oplock, NULL, cifs_sb->local_nls, | 594 | &fid, &oplock, NULL, cifs_sb->local_nls, |
| 593 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 595 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 594 | if (rc) { | 596 | if (!rc) { |
| 595 | cERROR(1, "Unable to open file to get ACL"); | 597 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); |
| 596 | goto out; | 598 | CIFSSMBClose(xid, tcon, fid); |
| 597 | } | 599 | } |
| 598 | 600 | ||
| 599 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); | ||
| 600 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); | ||
| 601 | |||
| 602 | CIFSSMBClose(xid, tcon, fid); | ||
| 603 | out: | ||
| 604 | cifs_put_tlink(tlink); | 601 | cifs_put_tlink(tlink); |
| 605 | FreeXid(xid); | 602 | FreeXid(xid); |
| 603 | |||
| 604 | cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); | ||
| 605 | if (rc) | ||
| 606 | return ERR_PTR(rc); | ||
| 606 | return pntsd; | 607 | return pntsd; |
| 607 | } | 608 | } |
| 608 | 609 | ||
| 609 | /* Retrieve an ACL from the server */ | 610 | /* Retrieve an ACL from the server */ |
| 610 | static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, | 611 | struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, |
| 611 | struct inode *inode, const char *path, | 612 | struct inode *inode, const char *path, |
| 612 | u32 *pacllen) | 613 | u32 *pacllen) |
| 613 | { | 614 | { |
| @@ -695,7 +696,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
| 695 | } | 696 | } |
| 696 | 697 | ||
| 697 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 698 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ |
| 698 | void | 699 | int |
| 699 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | 700 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
| 700 | struct inode *inode, const char *path, const __u16 *pfid) | 701 | struct inode *inode, const char *path, const __u16 *pfid) |
| 701 | { | 702 | { |
| @@ -711,17 +712,21 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | |||
| 711 | pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); | 712 | pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); |
| 712 | 713 | ||
| 713 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | 714 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ |
| 714 | if (pntsd) | 715 | if (IS_ERR(pntsd)) { |
| 716 | rc = PTR_ERR(pntsd); | ||
| 717 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); | ||
| 718 | } else { | ||
| 715 | rc = parse_sec_desc(pntsd, acllen, fattr); | 719 | rc = parse_sec_desc(pntsd, acllen, fattr); |
| 716 | if (rc) | 720 | kfree(pntsd); |
| 717 | cFYI(1, "parse sec desc failed rc = %d", rc); | 721 | if (rc) |
| 722 | cERROR(1, "parse sec desc failed rc = %d", rc); | ||
| 723 | } | ||
| 718 | 724 | ||
| 719 | kfree(pntsd); | 725 | return rc; |
| 720 | return; | ||
| 721 | } | 726 | } |
| 722 | 727 | ||
| 723 | /* Convert mode bits to an ACL so we can update the ACL on the server */ | 728 | /* Convert mode bits to an ACL so we can update the ACL on the server */ |
| 724 | int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) | 729 | int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode) |
| 725 | { | 730 | { |
| 726 | int rc = 0; | 731 | int rc = 0; |
| 727 | __u32 secdesclen = 0; | 732 | __u32 secdesclen = 0; |
| @@ -736,7 +741,10 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) | |||
| 736 | /* Add three ACEs for owner, group, everyone getting rid of | 741 | /* Add three ACEs for owner, group, everyone getting rid of |
| 737 | other ACEs as chmod disables ACEs and set the security descriptor */ | 742 | other ACEs as chmod disables ACEs and set the security descriptor */ |
| 738 | 743 | ||
| 739 | if (pntsd) { | 744 | if (IS_ERR(pntsd)) { |
| 745 | rc = PTR_ERR(pntsd); | ||
| 746 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); | ||
| 747 | } else { | ||
| 740 | /* allocate memory for the smb header, | 748 | /* allocate memory for the smb header, |
| 741 | set security descriptor request security descriptor | 749 | set security descriptor request security descriptor |
| 742 | parameters, and secuirty descriptor itself */ | 750 | parameters, and secuirty descriptor itself */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9c3789762ab7..76c8a906a63e 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -458,6 +458,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
| 458 | seq_printf(s, ",acl"); | 458 | seq_printf(s, ",acl"); |
| 459 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) | 459 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
| 460 | seq_printf(s, ",mfsymlinks"); | 460 | seq_printf(s, ",mfsymlinks"); |
| 461 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) | ||
| 462 | seq_printf(s, ",fsc"); | ||
| 461 | 463 | ||
| 462 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); | 464 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); |
| 463 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); | 465 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7ed69b6b5fe6..db961dc4fd3d 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -130,10 +130,12 @@ extern int cifs_get_file_info_unix(struct file *filp); | |||
| 130 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 130 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
| 131 | const unsigned char *search_path, | 131 | const unsigned char *search_path, |
| 132 | struct super_block *sb, int xid); | 132 | struct super_block *sb, int xid); |
| 133 | extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, | 133 | extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, |
| 134 | struct cifs_fattr *fattr, struct inode *inode, | 134 | struct cifs_fattr *fattr, struct inode *inode, |
| 135 | const char *path, const __u16 *pfid); | 135 | const char *path, const __u16 *pfid); |
| 136 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); | 136 | extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); |
| 137 | extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, | ||
| 138 | const char *, u32 *); | ||
| 137 | 139 | ||
| 138 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 140 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
| 139 | const char *); | 141 | const char *); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 251a17c03545..32fa4d9b5dbc 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -1352,6 +1352,11 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1352 | "supported. Instead set " | 1352 | "supported. Instead set " |
| 1353 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); | 1353 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); |
| 1354 | } else if (strnicmp(data, "fsc", 3) == 0) { | 1354 | } else if (strnicmp(data, "fsc", 3) == 0) { |
| 1355 | #ifndef CONFIG_CIFS_FSCACHE | ||
| 1356 | cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE" | ||
| 1357 | "kernel config option set"); | ||
| 1358 | return 1; | ||
| 1359 | #endif | ||
| 1355 | vol->fsc = true; | 1360 | vol->fsc = true; |
| 1356 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { | 1361 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { |
| 1357 | vol->mfsymlinks = true; | 1362 | vol->mfsymlinks = true; |
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 0eb87026cad3..548f06230a6d 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c | |||
| @@ -66,7 +66,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
| 66 | /* Search for server name delimiter */ | 66 | /* Search for server name delimiter */ |
| 67 | sep = memchr(hostname, '\\', len); | 67 | sep = memchr(hostname, '\\', len); |
| 68 | if (sep) | 68 | if (sep) |
| 69 | len = sep - unc; | 69 | len = sep - hostname; |
| 70 | else | 70 | else |
| 71 | cFYI(1, "%s: probably server name is whole unc: %s", | 71 | cFYI(1, "%s: probably server name is whole unc: %s", |
| 72 | __func__, unc); | 72 | __func__, unc); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 06c3e83fa387..b857ce5db775 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -2271,8 +2271,10 @@ void cifs_oplock_break_get(struct cifsFileInfo *cfile) | |||
| 2271 | 2271 | ||
| 2272 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) | 2272 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) |
| 2273 | { | 2273 | { |
| 2274 | struct super_block *sb = cfile->dentry->d_sb; | ||
| 2275 | |||
| 2274 | cifsFileInfo_put(cfile); | 2276 | cifsFileInfo_put(cfile); |
| 2275 | cifs_sb_deactive(cfile->dentry->d_sb); | 2277 | cifs_sb_deactive(sb); |
| 2276 | } | 2278 | } |
| 2277 | 2279 | ||
| 2278 | const struct address_space_operations cifs_addr_ops = { | 2280 | const struct address_space_operations cifs_addr_ops = { |
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index a2ad94efcfe6..297a43d0ff7f 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * fs/cifs/fscache.c - CIFS filesystem cache interface | 2 | * fs/cifs/fscache.c - CIFS filesystem cache interface |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2010 Novell, Inc. | 4 | * Copyright (c) 2010 Novell, Inc. |
| 5 | * Author(s): Suresh Jayaraman (sjayaraman@suse.de> | 5 | * Author(s): Suresh Jayaraman <sjayaraman@suse.de> |
| 6 | * | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU Lesser General Public License as published | 8 | * it under the terms of the GNU Lesser General Public License as published |
| @@ -67,10 +67,12 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode) | |||
| 67 | if (cifsi->fscache) | 67 | if (cifsi->fscache) |
| 68 | return; | 68 | return; |
| 69 | 69 | ||
| 70 | cifsi->fscache = fscache_acquire_cookie(tcon->fscache, | 70 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { |
| 71 | cifsi->fscache = fscache_acquire_cookie(tcon->fscache, | ||
| 71 | &cifs_fscache_inode_object_def, cifsi); | 72 | &cifs_fscache_inode_object_def, cifsi); |
| 72 | cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, | 73 | cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, |
| 73 | cifsi->fscache); | 74 | cifsi->fscache); |
| 75 | } | ||
| 74 | } | 76 | } |
| 75 | 77 | ||
| 76 | void cifs_fscache_release_inode_cookie(struct inode *inode) | 78 | void cifs_fscache_release_inode_cookie(struct inode *inode) |
| @@ -101,10 +103,8 @@ void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) | |||
| 101 | { | 103 | { |
| 102 | if ((filp->f_flags & O_ACCMODE) != O_RDONLY) | 104 | if ((filp->f_flags & O_ACCMODE) != O_RDONLY) |
| 103 | cifs_fscache_disable_inode_cookie(inode); | 105 | cifs_fscache_disable_inode_cookie(inode); |
| 104 | else { | 106 | else |
| 105 | cifs_fscache_enable_inode_cookie(inode); | 107 | cifs_fscache_enable_inode_cookie(inode); |
| 106 | cFYI(1, "CIFS: fscache inode cookie set"); | ||
| 107 | } | ||
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | void cifs_fscache_reset_inode_cookie(struct inode *inode) | 110 | void cifs_fscache_reset_inode_cookie(struct inode *inode) |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ef3a55bf86b6..28cb6e735943 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -689,8 +689,13 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 689 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 689 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 690 | /* fill in 0777 bits from ACL */ | 690 | /* fill in 0777 bits from ACL */ |
| 691 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 691 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
| 692 | cFYI(1, "Getting mode bits from ACL"); | 692 | rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, |
| 693 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); | 693 | pfid); |
| 694 | if (rc) { | ||
| 695 | cFYI(1, "%s: Getting ACL failed with error: %d", | ||
| 696 | __func__, rc); | ||
| 697 | goto cgii_exit; | ||
| 698 | } | ||
| 694 | } | 699 | } |
| 695 | #endif | 700 | #endif |
| 696 | 701 | ||
| @@ -881,8 +886,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
| 881 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 886 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
| 882 | xid, NULL); | 887 | xid, NULL); |
| 883 | 888 | ||
| 884 | if (!inode) | 889 | if (!inode) { |
| 885 | return ERR_PTR(rc); | 890 | inode = ERR_PTR(rc); |
| 891 | goto out; | ||
| 892 | } | ||
| 886 | 893 | ||
| 887 | #ifdef CONFIG_CIFS_FSCACHE | 894 | #ifdef CONFIG_CIFS_FSCACHE |
| 888 | /* populate tcon->resource_id */ | 895 | /* populate tcon->resource_id */ |
| @@ -898,13 +905,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
| 898 | inode->i_uid = cifs_sb->mnt_uid; | 905 | inode->i_uid = cifs_sb->mnt_uid; |
| 899 | inode->i_gid = cifs_sb->mnt_gid; | 906 | inode->i_gid = cifs_sb->mnt_gid; |
| 900 | } else if (rc) { | 907 | } else if (rc) { |
| 901 | kfree(full_path); | ||
| 902 | _FreeXid(xid); | ||
| 903 | iget_failed(inode); | 908 | iget_failed(inode); |
| 904 | return ERR_PTR(rc); | 909 | inode = ERR_PTR(rc); |
| 905 | } | 910 | } |
| 906 | 911 | ||
| 907 | 912 | out: | |
| 908 | kfree(full_path); | 913 | kfree(full_path); |
| 909 | /* can not call macro FreeXid here since in a void func | 914 | /* can not call macro FreeXid here since in a void func |
| 910 | * TODO: This is no longer true | 915 | * TODO: This is no longer true |
| @@ -1670,7 +1675,9 @@ cifs_inode_needs_reval(struct inode *inode) | |||
| 1670 | return false; | 1675 | return false; |
| 1671 | } | 1676 | } |
| 1672 | 1677 | ||
| 1673 | /* check invalid_mapping flag and zap the cache if it's set */ | 1678 | /* |
| 1679 | * Zap the cache. Called when invalid_mapping flag is set. | ||
| 1680 | */ | ||
| 1674 | static void | 1681 | static void |
| 1675 | cifs_invalidate_mapping(struct inode *inode) | 1682 | cifs_invalidate_mapping(struct inode *inode) |
| 1676 | { | 1683 | { |
| @@ -2115,9 +2122,14 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
| 2115 | if (attrs->ia_valid & ATTR_MODE) { | 2122 | if (attrs->ia_valid & ATTR_MODE) { |
| 2116 | rc = 0; | 2123 | rc = 0; |
| 2117 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2124 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 2118 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 2125 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
| 2119 | rc = mode_to_acl(inode, full_path, mode); | 2126 | rc = mode_to_cifs_acl(inode, full_path, mode); |
| 2120 | else | 2127 | if (rc) { |
| 2128 | cFYI(1, "%s: Setting ACL failed with error: %d", | ||
| 2129 | __func__, rc); | ||
| 2130 | goto cifs_setattr_exit; | ||
| 2131 | } | ||
| 2132 | } else | ||
| 2121 | #endif | 2133 | #endif |
| 2122 | if (((mode & S_IWUGO) == 0) && | 2134 | if (((mode & S_IWUGO) == 0) && |
| 2123 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 2135 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index ef7bb7b50f58..32d300e8f20e 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -226,26 +226,29 @@ static int initiate_cifs_search(const int xid, struct file *file) | |||
| 226 | char *full_path = NULL; | 226 | char *full_path = NULL; |
| 227 | struct cifsFileInfo *cifsFile; | 227 | struct cifsFileInfo *cifsFile; |
| 228 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 228 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| 229 | struct tcon_link *tlink; | 229 | struct tcon_link *tlink = NULL; |
| 230 | struct cifsTconInfo *pTcon; | 230 | struct cifsTconInfo *pTcon; |
| 231 | 231 | ||
| 232 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 233 | if (IS_ERR(tlink)) | ||
| 234 | return PTR_ERR(tlink); | ||
| 235 | pTcon = tlink_tcon(tlink); | ||
| 236 | |||
| 237 | if (file->private_data == NULL) | ||
| 238 | file->private_data = | ||
| 239 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | ||
| 240 | if (file->private_data == NULL) { | 232 | if (file->private_data == NULL) { |
| 241 | rc = -ENOMEM; | 233 | tlink = cifs_sb_tlink(cifs_sb); |
| 242 | goto error_exit; | 234 | if (IS_ERR(tlink)) |
| 235 | return PTR_ERR(tlink); | ||
| 236 | |||
| 237 | cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | ||
| 238 | if (cifsFile == NULL) { | ||
| 239 | rc = -ENOMEM; | ||
| 240 | goto error_exit; | ||
| 241 | } | ||
| 242 | file->private_data = cifsFile; | ||
| 243 | cifsFile->tlink = cifs_get_tlink(tlink); | ||
| 244 | pTcon = tlink_tcon(tlink); | ||
| 245 | } else { | ||
| 246 | cifsFile = file->private_data; | ||
| 247 | pTcon = tlink_tcon(cifsFile->tlink); | ||
| 243 | } | 248 | } |
| 244 | 249 | ||
| 245 | cifsFile = file->private_data; | ||
| 246 | cifsFile->invalidHandle = true; | 250 | cifsFile->invalidHandle = true; |
| 247 | cifsFile->srch_inf.endOfSearch = false; | 251 | cifsFile->srch_inf.endOfSearch = false; |
| 248 | cifsFile->tlink = cifs_get_tlink(tlink); | ||
| 249 | 252 | ||
| 250 | full_path = build_path_from_dentry(file->f_path.dentry); | 253 | full_path = build_path_from_dentry(file->f_path.dentry); |
| 251 | if (full_path == NULL) { | 254 | if (full_path == NULL) { |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index a264b744bb41..eae2a1491608 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
| @@ -30,10 +30,11 @@ | |||
| 30 | 30 | ||
| 31 | #define MAX_EA_VALUE_SIZE 65535 | 31 | #define MAX_EA_VALUE_SIZE 65535 |
| 32 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" | 32 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" |
| 33 | #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" | ||
| 33 | #define CIFS_XATTR_USER_PREFIX "user." | 34 | #define CIFS_XATTR_USER_PREFIX "user." |
| 34 | #define CIFS_XATTR_SYSTEM_PREFIX "system." | 35 | #define CIFS_XATTR_SYSTEM_PREFIX "system." |
| 35 | #define CIFS_XATTR_OS2_PREFIX "os2." | 36 | #define CIFS_XATTR_OS2_PREFIX "os2." |
| 36 | #define CIFS_XATTR_SECURITY_PREFIX ".security" | 37 | #define CIFS_XATTR_SECURITY_PREFIX "security." |
| 37 | #define CIFS_XATTR_TRUSTED_PREFIX "trusted." | 38 | #define CIFS_XATTR_TRUSTED_PREFIX "trusted." |
| 38 | #define XATTR_TRUSTED_PREFIX_LEN 8 | 39 | #define XATTR_TRUSTED_PREFIX_LEN 8 |
| 39 | #define XATTR_SECURITY_PREFIX_LEN 9 | 40 | #define XATTR_SECURITY_PREFIX_LEN 9 |
| @@ -277,29 +278,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
| 277 | cifs_sb->local_nls, | 278 | cifs_sb->local_nls, |
| 278 | cifs_sb->mnt_cifs_flags & | 279 | cifs_sb->mnt_cifs_flags & |
| 279 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 280 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 280 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 281 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
| 282 | __u16 fid; | ||
| 283 | int oplock = 0; | ||
| 284 | struct cifs_ntsd *pacl = NULL; | ||
| 285 | __u32 buflen = 0; | ||
| 286 | if (experimEnabled) | ||
| 287 | rc = CIFSSMBOpen(xid, pTcon, full_path, | ||
| 288 | FILE_OPEN, GENERIC_READ, 0, &fid, | ||
| 289 | &oplock, NULL, cifs_sb->local_nls, | ||
| 290 | cifs_sb->mnt_cifs_flags & | ||
| 291 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 292 | /* else rc is EOPNOTSUPP from above */ | ||
| 293 | |||
| 294 | if (rc == 0) { | ||
| 295 | rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl, | ||
| 296 | &buflen); | ||
| 297 | CIFSSMBClose(xid, pTcon, fid); | ||
| 298 | } | ||
| 299 | } | ||
| 300 | #endif /* EXPERIMENTAL */ | ||
| 301 | #else | 281 | #else |
| 302 | cFYI(1, "query POSIX ACL not supported yet"); | 282 | cFYI(1, "Query POSIX ACL not supported yet"); |
| 303 | #endif /* CONFIG_CIFS_POSIX */ | 283 | #endif /* CONFIG_CIFS_POSIX */ |
| 304 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, | 284 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, |
| 305 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { | 285 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { |
| @@ -311,8 +291,33 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
| 311 | cifs_sb->mnt_cifs_flags & | 291 | cifs_sb->mnt_cifs_flags & |
| 312 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 292 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 313 | #else | 293 | #else |
| 314 | cFYI(1, "query POSIX default ACL not supported yet"); | 294 | cFYI(1, "Query POSIX default ACL not supported yet"); |
| 315 | #endif | 295 | #endif /* CONFIG_CIFS_POSIX */ |
| 296 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | ||
| 297 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | ||
| 298 | #ifdef CONFIG_CIFS_ACL | ||
| 299 | u32 acllen; | ||
| 300 | struct cifs_ntsd *pacl; | ||
| 301 | |||
| 302 | pacl = get_cifs_acl(cifs_sb, direntry->d_inode, | ||
| 303 | full_path, &acllen); | ||
| 304 | if (IS_ERR(pacl)) { | ||
| 305 | rc = PTR_ERR(pacl); | ||
| 306 | cERROR(1, "%s: error %zd getting sec desc", | ||
| 307 | __func__, rc); | ||
| 308 | } else { | ||
| 309 | if (ea_value) { | ||
| 310 | if (acllen > buf_size) | ||
| 311 | acllen = -ERANGE; | ||
| 312 | else | ||
| 313 | memcpy(ea_value, pacl, acllen); | ||
| 314 | } | ||
| 315 | rc = acllen; | ||
| 316 | kfree(pacl); | ||
| 317 | } | ||
| 318 | #else | ||
| 319 | cFYI(1, "Query CIFS ACL not supported yet"); | ||
| 320 | #endif /* CONFIG_CIFS_ACL */ | ||
| 316 | } else if (strncmp(ea_name, | 321 | } else if (strncmp(ea_name, |
| 317 | CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { | 322 | CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { |
| 318 | cFYI(1, "Trusted xattr namespace not supported yet"); | 323 | cFYI(1, "Trusted xattr namespace not supported yet"); |
diff --git a/fs/compat.c b/fs/compat.c index c580c322fa6b..eb1740ac8c0a 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
| @@ -1350,6 +1350,10 @@ static int compat_count(compat_uptr_t __user *argv, int max) | |||
| 1350 | argv++; | 1350 | argv++; |
| 1351 | if (i++ >= max) | 1351 | if (i++ >= max) |
| 1352 | return -E2BIG; | 1352 | return -E2BIG; |
| 1353 | |||
| 1354 | if (fatal_signal_pending(current)) | ||
| 1355 | return -ERESTARTNOHAND; | ||
| 1356 | cond_resched(); | ||
| 1353 | } | 1357 | } |
| 1354 | } | 1358 | } |
| 1355 | return i; | 1359 | return i; |
| @@ -1391,6 +1395,12 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, | |||
| 1391 | while (len > 0) { | 1395 | while (len > 0) { |
| 1392 | int offset, bytes_to_copy; | 1396 | int offset, bytes_to_copy; |
| 1393 | 1397 | ||
| 1398 | if (fatal_signal_pending(current)) { | ||
| 1399 | ret = -ERESTARTNOHAND; | ||
| 1400 | goto out; | ||
| 1401 | } | ||
| 1402 | cond_resched(); | ||
| 1403 | |||
| 1394 | offset = pos % PAGE_SIZE; | 1404 | offset = pos % PAGE_SIZE; |
| 1395 | if (offset == 0) | 1405 | if (offset == 0) |
| 1396 | offset = PAGE_SIZE; | 1406 | offset = PAGE_SIZE; |
| @@ -1407,18 +1417,8 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, | |||
| 1407 | if (!kmapped_page || kpos != (pos & PAGE_MASK)) { | 1417 | if (!kmapped_page || kpos != (pos & PAGE_MASK)) { |
| 1408 | struct page *page; | 1418 | struct page *page; |
| 1409 | 1419 | ||
| 1410 | #ifdef CONFIG_STACK_GROWSUP | 1420 | page = get_arg_page(bprm, pos, 1); |
| 1411 | ret = expand_stack_downwards(bprm->vma, pos); | 1421 | if (!page) { |
| 1412 | if (ret < 0) { | ||
| 1413 | /* We've exceed the stack rlimit. */ | ||
| 1414 | ret = -E2BIG; | ||
| 1415 | goto out; | ||
| 1416 | } | ||
| 1417 | #endif | ||
| 1418 | ret = get_user_pages(current, bprm->mm, pos, | ||
| 1419 | 1, 1, 1, &page, NULL); | ||
| 1420 | if (ret <= 0) { | ||
| 1421 | /* We've exceed the stack rlimit. */ | ||
| 1422 | ret = -E2BIG; | 1422 | ret = -E2BIG; |
| 1423 | goto out; | 1423 | goto out; |
| 1424 | } | 1424 | } |
| @@ -1539,8 +1539,10 @@ int compat_do_execve(char * filename, | |||
| 1539 | return retval; | 1539 | return retval; |
| 1540 | 1540 | ||
| 1541 | out: | 1541 | out: |
| 1542 | if (bprm->mm) | 1542 | if (bprm->mm) { |
| 1543 | acct_arg_size(bprm, 0); | ||
| 1543 | mmput(bprm->mm); | 1544 | mmput(bprm->mm); |
| 1545 | } | ||
| 1544 | 1546 | ||
| 1545 | out_file: | 1547 | out_file: |
| 1546 | if (bprm->file) { | 1548 | if (bprm->file) { |
| @@ -164,7 +164,26 @@ out: | |||
| 164 | 164 | ||
| 165 | #ifdef CONFIG_MMU | 165 | #ifdef CONFIG_MMU |
| 166 | 166 | ||
| 167 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 167 | void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) |
| 168 | { | ||
| 169 | struct mm_struct *mm = current->mm; | ||
| 170 | long diff = (long)(pages - bprm->vma_pages); | ||
| 171 | |||
| 172 | if (!mm || !diff) | ||
| 173 | return; | ||
| 174 | |||
| 175 | bprm->vma_pages = pages; | ||
| 176 | |||
| 177 | #ifdef SPLIT_RSS_COUNTING | ||
| 178 | add_mm_counter(mm, MM_ANONPAGES, diff); | ||
| 179 | #else | ||
| 180 | spin_lock(&mm->page_table_lock); | ||
| 181 | add_mm_counter(mm, MM_ANONPAGES, diff); | ||
| 182 | spin_unlock(&mm->page_table_lock); | ||
| 183 | #endif | ||
| 184 | } | ||
| 185 | |||
| 186 | struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | ||
| 168 | int write) | 187 | int write) |
| 169 | { | 188 | { |
| 170 | struct page *page; | 189 | struct page *page; |
| @@ -186,6 +205,8 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
| 186 | unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; | 205 | unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; |
| 187 | struct rlimit *rlim; | 206 | struct rlimit *rlim; |
| 188 | 207 | ||
| 208 | acct_arg_size(bprm, size / PAGE_SIZE); | ||
| 209 | |||
| 189 | /* | 210 | /* |
| 190 | * We've historically supported up to 32 pages (ARG_MAX) | 211 | * We've historically supported up to 32 pages (ARG_MAX) |
| 191 | * of argument strings even with small stacks | 212 | * of argument strings even with small stacks |
| @@ -276,7 +297,11 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len) | |||
| 276 | 297 | ||
| 277 | #else | 298 | #else |
| 278 | 299 | ||
| 279 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 300 | void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) |
| 301 | { | ||
| 302 | } | ||
| 303 | |||
| 304 | struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | ||
| 280 | int write) | 305 | int write) |
| 281 | { | 306 | { |
| 282 | struct page *page; | 307 | struct page *page; |
| @@ -1003,6 +1028,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
| 1003 | /* | 1028 | /* |
| 1004 | * Release all of the old mmap stuff | 1029 | * Release all of the old mmap stuff |
| 1005 | */ | 1030 | */ |
| 1031 | acct_arg_size(bprm, 0); | ||
| 1006 | retval = exec_mmap(bprm->mm); | 1032 | retval = exec_mmap(bprm->mm); |
| 1007 | if (retval) | 1033 | if (retval) |
| 1008 | goto out; | 1034 | goto out; |
| @@ -1426,8 +1452,10 @@ int do_execve(const char * filename, | |||
| 1426 | return retval; | 1452 | return retval; |
| 1427 | 1453 | ||
| 1428 | out: | 1454 | out: |
| 1429 | if (bprm->mm) | 1455 | if (bprm->mm) { |
| 1430 | mmput (bprm->mm); | 1456 | acct_arg_size(bprm, 0); |
| 1457 | mmput(bprm->mm); | ||
| 1458 | } | ||
| 1431 | 1459 | ||
| 1432 | out_file: | 1460 | out_file: |
| 1433 | if (bprm->file) { | 1461 | if (bprm->file) { |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 8ea4a4180a87..f0a384e2ae63 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -395,13 +395,9 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct x | |||
| 395 | static | 395 | static |
| 396 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) | 396 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) |
| 397 | { | 397 | { |
| 398 | struct nfs_inode *node; | ||
| 399 | if (dentry->d_inode == NULL) | 398 | if (dentry->d_inode == NULL) |
| 400 | goto different; | 399 | goto different; |
| 401 | node = NFS_I(dentry->d_inode); | 400 | if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0) |
| 402 | if (node->fh.size != entry->fh->size) | ||
| 403 | goto different; | ||
| 404 | if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0) | ||
| 405 | goto different; | 401 | goto different; |
| 406 | return 1; | 402 | return 1; |
| 407 | different: | 403 | different: |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 52c7557f3e25..9f26ac9be2a4 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
| @@ -1964,8 +1964,10 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g | |||
| 1964 | if (reg == NULL) | 1964 | if (reg == NULL) |
| 1965 | return ERR_PTR(-ENOMEM); | 1965 | return ERR_PTR(-ENOMEM); |
| 1966 | 1966 | ||
| 1967 | if (strlen(name) > O2HB_MAX_REGION_NAME_LEN) | 1967 | if (strlen(name) > O2HB_MAX_REGION_NAME_LEN) { |
| 1968 | return ERR_PTR(-ENAMETOOLONG); | 1968 | ret = -ENAMETOOLONG; |
| 1969 | goto free; | ||
| 1970 | } | ||
| 1969 | 1971 | ||
| 1970 | spin_lock(&o2hb_live_lock); | 1972 | spin_lock(&o2hb_live_lock); |
| 1971 | reg->hr_region_num = 0; | 1973 | reg->hr_region_num = 0; |
| @@ -1974,7 +1976,8 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g | |||
| 1974 | O2NM_MAX_REGIONS); | 1976 | O2NM_MAX_REGIONS); |
| 1975 | if (reg->hr_region_num >= O2NM_MAX_REGIONS) { | 1977 | if (reg->hr_region_num >= O2NM_MAX_REGIONS) { |
| 1976 | spin_unlock(&o2hb_live_lock); | 1978 | spin_unlock(&o2hb_live_lock); |
| 1977 | return ERR_PTR(-EFBIG); | 1979 | ret = -EFBIG; |
| 1980 | goto free; | ||
| 1978 | } | 1981 | } |
| 1979 | set_bit(reg->hr_region_num, o2hb_region_bitmap); | 1982 | set_bit(reg->hr_region_num, o2hb_region_bitmap); |
| 1980 | } | 1983 | } |
| @@ -1986,10 +1989,13 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g | |||
| 1986 | ret = o2hb_debug_region_init(reg, o2hb_debug_dir); | 1989 | ret = o2hb_debug_region_init(reg, o2hb_debug_dir); |
| 1987 | if (ret) { | 1990 | if (ret) { |
| 1988 | config_item_put(®->hr_item); | 1991 | config_item_put(®->hr_item); |
| 1989 | return ERR_PTR(ret); | 1992 | goto free; |
| 1990 | } | 1993 | } |
| 1991 | 1994 | ||
| 1992 | return ®->hr_item; | 1995 | return ®->hr_item; |
| 1996 | free: | ||
| 1997 | kfree(reg); | ||
| 1998 | return ERR_PTR(ret); | ||
| 1993 | } | 1999 | } |
| 1994 | 2000 | ||
| 1995 | static void o2hb_heartbeat_group_drop_item(struct config_group *group, | 2001 | static void o2hb_heartbeat_group_drop_item(struct config_group *group, |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index edaded48e7e9..895532ac4d98 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
| @@ -476,7 +476,6 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
| 476 | 476 | ||
| 477 | out: | 477 | out: |
| 478 | iput(inode); | 478 | iput(inode); |
| 479 | ocfs2_dentry_attach_gen(dentry); | ||
| 480 | } | 479 | } |
| 481 | 480 | ||
| 482 | /* | 481 | /* |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 58a93b953735..cc2aaa96cfe5 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
| @@ -959,7 +959,7 @@ static int dlm_match_regions(struct dlm_ctxt *dlm, | |||
| 959 | r += O2HB_MAX_REGION_NAME_LEN; | 959 | r += O2HB_MAX_REGION_NAME_LEN; |
| 960 | } | 960 | } |
| 961 | 961 | ||
| 962 | local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL); | 962 | local = kmalloc(sizeof(qr->qr_regions), GFP_ATOMIC); |
| 963 | if (!local) { | 963 | if (!local) { |
| 964 | status = -ENOMEM; | 964 | status = -ENOMEM; |
| 965 | goto bail; | 965 | goto bail; |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 1efea3615589..70dd3b1798f1 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
| @@ -159,9 +159,9 @@ struct ocfs2_lock_res { | |||
| 159 | char l_name[OCFS2_LOCK_ID_MAX_LEN]; | 159 | char l_name[OCFS2_LOCK_ID_MAX_LEN]; |
| 160 | unsigned int l_ro_holders; | 160 | unsigned int l_ro_holders; |
| 161 | unsigned int l_ex_holders; | 161 | unsigned int l_ex_holders; |
| 162 | char l_level; | 162 | signed char l_level; |
| 163 | char l_requested; | 163 | signed char l_requested; |
| 164 | char l_blocking; | 164 | signed char l_blocking; |
| 165 | 165 | ||
| 166 | /* Data packed - type enum ocfs2_lock_type */ | 166 | /* Data packed - type enum ocfs2_lock_type */ |
| 167 | unsigned char l_type; | 167 | unsigned char l_type; |
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c index 252e7c82f929..a5ebe421195f 100644 --- a/fs/ocfs2/stack_user.c +++ b/fs/ocfs2/stack_user.c | |||
| @@ -190,7 +190,7 @@ static struct ocfs2_live_connection *ocfs2_connection_find(const char *name) | |||
| 190 | return c; | 190 | return c; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | return c; | 193 | return NULL; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | /* | 196 | /* |
diff --git a/fs/proc/base.c b/fs/proc/base.c index f3d02ca461ec..182845147fe4 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -1574,7 +1574,7 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen) | |||
| 1574 | if (!tmp) | 1574 | if (!tmp) |
| 1575 | return -ENOMEM; | 1575 | return -ENOMEM; |
| 1576 | 1576 | ||
| 1577 | pathname = d_path_with_unreachable(path, tmp, PAGE_SIZE); | 1577 | pathname = d_path(path, tmp, PAGE_SIZE); |
| 1578 | len = PTR_ERR(pathname); | 1578 | len = PTR_ERR(pathname); |
| 1579 | if (IS_ERR(pathname)) | 1579 | if (IS_ERR(pathname)) |
| 1580 | goto out; | 1580 | goto out; |
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 536d697a8a28..90d2fcb67a31 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c | |||
| @@ -472,7 +472,9 @@ int reiserfs_acl_chmod(struct inode *inode) | |||
| 472 | struct reiserfs_transaction_handle th; | 472 | struct reiserfs_transaction_handle th; |
| 473 | size_t size = reiserfs_xattr_nblocks(inode, | 473 | size_t size = reiserfs_xattr_nblocks(inode, |
| 474 | reiserfs_acl_size(clone->a_count)); | 474 | reiserfs_acl_size(clone->a_count)); |
| 475 | reiserfs_write_lock(inode->i_sb); | 475 | int depth; |
| 476 | |||
| 477 | depth = reiserfs_write_lock_once(inode->i_sb); | ||
| 476 | error = journal_begin(&th, inode->i_sb, size * 2); | 478 | error = journal_begin(&th, inode->i_sb, size * 2); |
| 477 | if (!error) { | 479 | if (!error) { |
| 478 | int error2; | 480 | int error2; |
| @@ -482,7 +484,7 @@ int reiserfs_acl_chmod(struct inode *inode) | |||
| 482 | if (error2) | 484 | if (error2) |
| 483 | error = error2; | 485 | error = error2; |
| 484 | } | 486 | } |
| 485 | reiserfs_write_unlock(inode->i_sb); | 487 | reiserfs_write_unlock_once(inode->i_sb, depth); |
| 486 | } | 488 | } |
| 487 | posix_acl_release(clone); | 489 | posix_acl_release(clone); |
| 488 | return error; | 490 | return error; |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 7d287afccde5..691f61223ed6 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
| @@ -934,7 +934,6 @@ xfs_aops_discard_page( | |||
| 934 | struct xfs_inode *ip = XFS_I(inode); | 934 | struct xfs_inode *ip = XFS_I(inode); |
| 935 | struct buffer_head *bh, *head; | 935 | struct buffer_head *bh, *head; |
| 936 | loff_t offset = page_offset(page); | 936 | loff_t offset = page_offset(page); |
| 937 | ssize_t len = 1 << inode->i_blkbits; | ||
| 938 | 937 | ||
| 939 | if (!xfs_is_delayed_page(page, IO_DELAY)) | 938 | if (!xfs_is_delayed_page(page, IO_DELAY)) |
| 940 | goto out_invalidate; | 939 | goto out_invalidate; |
| @@ -949,58 +948,14 @@ xfs_aops_discard_page( | |||
| 949 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 948 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
| 950 | bh = head = page_buffers(page); | 949 | bh = head = page_buffers(page); |
| 951 | do { | 950 | do { |
| 952 | int done; | ||
| 953 | xfs_fileoff_t offset_fsb; | ||
| 954 | xfs_bmbt_irec_t imap; | ||
| 955 | int nimaps = 1; | ||
| 956 | int error; | 951 | int error; |
| 957 | xfs_fsblock_t firstblock; | 952 | xfs_fileoff_t start_fsb; |
| 958 | xfs_bmap_free_t flist; | ||
| 959 | 953 | ||
| 960 | if (!buffer_delay(bh)) | 954 | if (!buffer_delay(bh)) |
| 961 | goto next_buffer; | 955 | goto next_buffer; |
| 962 | 956 | ||
| 963 | offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); | 957 | start_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); |
| 964 | 958 | error = xfs_bmap_punch_delalloc_range(ip, start_fsb, 1); | |
| 965 | /* | ||
| 966 | * Map the range first and check that it is a delalloc extent | ||
| 967 | * before trying to unmap the range. Otherwise we will be | ||
| 968 | * trying to remove a real extent (which requires a | ||
| 969 | * transaction) or a hole, which is probably a bad idea... | ||
| 970 | */ | ||
| 971 | error = xfs_bmapi(NULL, ip, offset_fsb, 1, | ||
| 972 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | ||
| 973 | &nimaps, NULL); | ||
| 974 | |||
| 975 | if (error) { | ||
| 976 | /* something screwed, just bail */ | ||
| 977 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
| 978 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | ||
| 979 | "page discard failed delalloc mapping lookup."); | ||
| 980 | } | ||
| 981 | break; | ||
| 982 | } | ||
| 983 | if (!nimaps) { | ||
| 984 | /* nothing there */ | ||
| 985 | goto next_buffer; | ||
| 986 | } | ||
| 987 | if (imap.br_startblock != DELAYSTARTBLOCK) { | ||
| 988 | /* been converted, ignore */ | ||
| 989 | goto next_buffer; | ||
| 990 | } | ||
| 991 | WARN_ON(imap.br_blockcount == 0); | ||
| 992 | |||
| 993 | /* | ||
| 994 | * Note: while we initialise the firstblock/flist pair, they | ||
| 995 | * should never be used because blocks should never be | ||
| 996 | * allocated or freed for a delalloc extent and hence we need | ||
| 997 | * don't cancel or finish them after the xfs_bunmapi() call. | ||
| 998 | */ | ||
| 999 | xfs_bmap_init(&flist, &firstblock); | ||
| 1000 | error = xfs_bunmapi(NULL, ip, offset_fsb, 1, 0, 1, &firstblock, | ||
| 1001 | &flist, &done); | ||
| 1002 | |||
| 1003 | ASSERT(!flist.xbf_count && !flist.xbf_first); | ||
| 1004 | if (error) { | 959 | if (error) { |
| 1005 | /* something screwed, just bail */ | 960 | /* something screwed, just bail */ |
| 1006 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | 961 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
| @@ -1010,7 +965,7 @@ xfs_aops_discard_page( | |||
| 1010 | break; | 965 | break; |
| 1011 | } | 966 | } |
| 1012 | next_buffer: | 967 | next_buffer: |
| 1013 | offset += len; | 968 | offset += 1 << inode->i_blkbits; |
| 1014 | 969 | ||
| 1015 | } while ((bh = bh->b_this_page) != head); | 970 | } while ((bh = bh->b_this_page) != head); |
| 1016 | 971 | ||
| @@ -1505,11 +1460,42 @@ xfs_vm_write_failed( | |||
| 1505 | struct inode *inode = mapping->host; | 1460 | struct inode *inode = mapping->host; |
| 1506 | 1461 | ||
| 1507 | if (to > inode->i_size) { | 1462 | if (to > inode->i_size) { |
| 1508 | struct iattr ia = { | 1463 | /* |
| 1509 | .ia_valid = ATTR_SIZE | ATTR_FORCE, | 1464 | * punch out the delalloc blocks we have already allocated. We |
| 1510 | .ia_size = inode->i_size, | 1465 | * don't call xfs_setattr() to do this as we may be in the |
| 1511 | }; | 1466 | * middle of a multi-iovec write and so the vfs inode->i_size |
| 1512 | xfs_setattr(XFS_I(inode), &ia, XFS_ATTR_NOLOCK); | 1467 | * will not match the xfs ip->i_size and so it will zero too |
| 1468 | * much. Hence we jus truncate the page cache to zero what is | ||
| 1469 | * necessary and punch the delalloc blocks directly. | ||
| 1470 | */ | ||
| 1471 | struct xfs_inode *ip = XFS_I(inode); | ||
| 1472 | xfs_fileoff_t start_fsb; | ||
| 1473 | xfs_fileoff_t end_fsb; | ||
| 1474 | int error; | ||
| 1475 | |||
| 1476 | truncate_pagecache(inode, to, inode->i_size); | ||
| 1477 | |||
| 1478 | /* | ||
| 1479 | * Check if there are any blocks that are outside of i_size | ||
| 1480 | * that need to be trimmed back. | ||
| 1481 | */ | ||
| 1482 | start_fsb = XFS_B_TO_FSB(ip->i_mount, inode->i_size) + 1; | ||
| 1483 | end_fsb = XFS_B_TO_FSB(ip->i_mount, to); | ||
| 1484 | if (end_fsb <= start_fsb) | ||
| 1485 | return; | ||
| 1486 | |||
| 1487 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 1488 | error = xfs_bmap_punch_delalloc_range(ip, start_fsb, | ||
| 1489 | end_fsb - start_fsb); | ||
| 1490 | if (error) { | ||
| 1491 | /* something screwed, just bail */ | ||
| 1492 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
| 1493 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | ||
| 1494 | "xfs_vm_write_failed: unable to clean up ino %lld", | ||
| 1495 | ip->i_ino); | ||
| 1496 | } | ||
| 1497 | } | ||
| 1498 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
| 1513 | } | 1499 | } |
| 1514 | } | 1500 | } |
| 1515 | 1501 | ||
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index aa1d353def29..4c5deb6e9e31 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
| @@ -488,29 +488,16 @@ found: | |||
| 488 | spin_unlock(&pag->pag_buf_lock); | 488 | spin_unlock(&pag->pag_buf_lock); |
| 489 | xfs_perag_put(pag); | 489 | xfs_perag_put(pag); |
| 490 | 490 | ||
| 491 | /* Attempt to get the semaphore without sleeping, | 491 | if (xfs_buf_cond_lock(bp)) { |
| 492 | * if this does not work then we need to drop the | 492 | /* failed, so wait for the lock if requested. */ |
| 493 | * spinlock and do a hard attempt on the semaphore. | ||
| 494 | */ | ||
| 495 | if (down_trylock(&bp->b_sema)) { | ||
| 496 | if (!(flags & XBF_TRYLOCK)) { | 493 | if (!(flags & XBF_TRYLOCK)) { |
| 497 | /* wait for buffer ownership */ | ||
| 498 | xfs_buf_lock(bp); | 494 | xfs_buf_lock(bp); |
| 499 | XFS_STATS_INC(xb_get_locked_waited); | 495 | XFS_STATS_INC(xb_get_locked_waited); |
| 500 | } else { | 496 | } else { |
| 501 | /* We asked for a trylock and failed, no need | ||
| 502 | * to look at file offset and length here, we | ||
| 503 | * know that this buffer at least overlaps our | ||
| 504 | * buffer and is locked, therefore our buffer | ||
| 505 | * either does not exist, or is this buffer. | ||
| 506 | */ | ||
| 507 | xfs_buf_rele(bp); | 497 | xfs_buf_rele(bp); |
| 508 | XFS_STATS_INC(xb_busy_locked); | 498 | XFS_STATS_INC(xb_busy_locked); |
| 509 | return NULL; | 499 | return NULL; |
| 510 | } | 500 | } |
| 511 | } else { | ||
| 512 | /* trylock worked */ | ||
| 513 | XB_SET_OWNER(bp); | ||
| 514 | } | 501 | } |
| 515 | 502 | ||
| 516 | if (bp->b_flags & XBF_STALE) { | 503 | if (bp->b_flags & XBF_STALE) { |
| @@ -876,10 +863,18 @@ xfs_buf_rele( | |||
| 876 | */ | 863 | */ |
| 877 | 864 | ||
| 878 | /* | 865 | /* |
| 879 | * Locks a buffer object, if it is not already locked. | 866 | * Locks a buffer object, if it is not already locked. Note that this in |
| 880 | * Note that this in no way locks the underlying pages, so it is only | 867 | * no way locks the underlying pages, so it is only useful for |
| 881 | * useful for synchronizing concurrent use of buffer objects, not for | 868 | * synchronizing concurrent use of buffer objects, not for synchronizing |
| 882 | * synchronizing independent access to the underlying pages. | 869 | * independent access to the underlying pages. |
| 870 | * | ||
| 871 | * If we come across a stale, pinned, locked buffer, we know that we are | ||
| 872 | * being asked to lock a buffer that has been reallocated. Because it is | ||
| 873 | * pinned, we know that the log has not been pushed to disk and hence it | ||
| 874 | * will still be locked. Rather than continuing to have trylock attempts | ||
| 875 | * fail until someone else pushes the log, push it ourselves before | ||
| 876 | * returning. This means that the xfsaild will not get stuck trying | ||
| 877 | * to push on stale inode buffers. | ||
| 883 | */ | 878 | */ |
| 884 | int | 879 | int |
| 885 | xfs_buf_cond_lock( | 880 | xfs_buf_cond_lock( |
| @@ -890,6 +885,8 @@ xfs_buf_cond_lock( | |||
| 890 | locked = down_trylock(&bp->b_sema) == 0; | 885 | locked = down_trylock(&bp->b_sema) == 0; |
| 891 | if (locked) | 886 | if (locked) |
| 892 | XB_SET_OWNER(bp); | 887 | XB_SET_OWNER(bp); |
| 888 | else if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE)) | ||
| 889 | xfs_log_force(bp->b_target->bt_mount, 0); | ||
| 893 | 890 | ||
| 894 | trace_xfs_buf_cond_lock(bp, _RET_IP_); | 891 | trace_xfs_buf_cond_lock(bp, _RET_IP_); |
| 895 | return locked ? 0 : -EBUSY; | 892 | return locked ? 0 : -EBUSY; |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 8abd12e32e13..4111cd3966c7 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
| @@ -5471,8 +5471,13 @@ xfs_getbmap( | |||
| 5471 | if (error) | 5471 | if (error) |
| 5472 | goto out_unlock_iolock; | 5472 | goto out_unlock_iolock; |
| 5473 | } | 5473 | } |
| 5474 | 5474 | /* | |
| 5475 | ASSERT(ip->i_delayed_blks == 0); | 5475 | * even after flushing the inode, there can still be delalloc |
| 5476 | * blocks on the inode beyond EOF due to speculative | ||
| 5477 | * preallocation. These are not removed until the release | ||
| 5478 | * function is called or the inode is inactivated. Hence we | ||
| 5479 | * cannot assert here that ip->i_delayed_blks == 0. | ||
| 5480 | */ | ||
| 5476 | } | 5481 | } |
| 5477 | 5482 | ||
| 5478 | lock = xfs_ilock_map_shared(ip); | 5483 | lock = xfs_ilock_map_shared(ip); |
| @@ -6070,3 +6075,79 @@ xfs_bmap_disk_count_leaves( | |||
| 6070 | *count += xfs_bmbt_disk_get_blockcount(frp); | 6075 | *count += xfs_bmbt_disk_get_blockcount(frp); |
| 6071 | } | 6076 | } |
| 6072 | } | 6077 | } |
| 6078 | |||
| 6079 | /* | ||
| 6080 | * dead simple method of punching delalyed allocation blocks from a range in | ||
| 6081 | * the inode. Walks a block at a time so will be slow, but is only executed in | ||
| 6082 | * rare error cases so the overhead is not critical. This will alays punch out | ||
| 6083 | * both the start and end blocks, even if the ranges only partially overlap | ||
| 6084 | * them, so it is up to the caller to ensure that partial blocks are not | ||
| 6085 | * passed in. | ||
| 6086 | */ | ||
| 6087 | int | ||
| 6088 | xfs_bmap_punch_delalloc_range( | ||
| 6089 | struct xfs_inode *ip, | ||
| 6090 | xfs_fileoff_t start_fsb, | ||
| 6091 | xfs_fileoff_t length) | ||
| 6092 | { | ||
| 6093 | xfs_fileoff_t remaining = length; | ||
| 6094 | int error = 0; | ||
| 6095 | |||
| 6096 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
| 6097 | |||
| 6098 | do { | ||
| 6099 | int done; | ||
| 6100 | xfs_bmbt_irec_t imap; | ||
| 6101 | int nimaps = 1; | ||
| 6102 | xfs_fsblock_t firstblock; | ||
| 6103 | xfs_bmap_free_t flist; | ||
| 6104 | |||
| 6105 | /* | ||
| 6106 | * Map the range first and check that it is a delalloc extent | ||
| 6107 | * before trying to unmap the range. Otherwise we will be | ||
| 6108 | * trying to remove a real extent (which requires a | ||
| 6109 | * transaction) or a hole, which is probably a bad idea... | ||
| 6110 | */ | ||
| 6111 | error = xfs_bmapi(NULL, ip, start_fsb, 1, | ||
| 6112 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | ||
| 6113 | &nimaps, NULL); | ||
| 6114 | |||
| 6115 | if (error) { | ||
| 6116 | /* something screwed, just bail */ | ||
| 6117 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
| 6118 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | ||
| 6119 | "Failed delalloc mapping lookup ino %lld fsb %lld.", | ||
| 6120 | ip->i_ino, start_fsb); | ||
| 6121 | } | ||
| 6122 | break; | ||
| 6123 | } | ||
| 6124 | if (!nimaps) { | ||
| 6125 | /* nothing there */ | ||
| 6126 | goto next_block; | ||
| 6127 | } | ||
| 6128 | if (imap.br_startblock != DELAYSTARTBLOCK) { | ||
| 6129 | /* been converted, ignore */ | ||
| 6130 | goto next_block; | ||
| 6131 | } | ||
| 6132 | WARN_ON(imap.br_blockcount == 0); | ||
| 6133 | |||
| 6134 | /* | ||
| 6135 | * Note: while we initialise the firstblock/flist pair, they | ||
| 6136 | * should never be used because blocks should never be | ||
| 6137 | * allocated or freed for a delalloc extent and hence we need | ||
| 6138 | * don't cancel or finish them after the xfs_bunmapi() call. | ||
| 6139 | */ | ||
| 6140 | xfs_bmap_init(&flist, &firstblock); | ||
| 6141 | error = xfs_bunmapi(NULL, ip, start_fsb, 1, 0, 1, &firstblock, | ||
| 6142 | &flist, &done); | ||
| 6143 | if (error) | ||
| 6144 | break; | ||
| 6145 | |||
| 6146 | ASSERT(!flist.xbf_count && !flist.xbf_first); | ||
| 6147 | next_block: | ||
| 6148 | start_fsb++; | ||
| 6149 | remaining--; | ||
| 6150 | } while(remaining > 0); | ||
| 6151 | |||
| 6152 | return error; | ||
| 6153 | } | ||
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 71ec9b6ecdfc..3651191daea1 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
| @@ -394,6 +394,11 @@ xfs_bmap_count_blocks( | |||
| 394 | int whichfork, | 394 | int whichfork, |
| 395 | int *count); | 395 | int *count); |
| 396 | 396 | ||
| 397 | int | ||
| 398 | xfs_bmap_punch_delalloc_range( | ||
| 399 | struct xfs_inode *ip, | ||
| 400 | xfs_fileoff_t start_fsb, | ||
| 401 | xfs_fileoff_t length); | ||
| 397 | #endif /* __KERNEL__ */ | 402 | #endif /* __KERNEL__ */ |
| 398 | 403 | ||
| 399 | #endif /* __XFS_BMAP_H__ */ | 404 | #endif /* __XFS_BMAP_H__ */ |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 3b9582c60a22..e60490bc00a6 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
| @@ -377,6 +377,19 @@ xfs_swap_extents( | |||
| 377 | ip->i_d.di_format = tip->i_d.di_format; | 377 | ip->i_d.di_format = tip->i_d.di_format; |
| 378 | tip->i_d.di_format = tmp; | 378 | tip->i_d.di_format = tmp; |
| 379 | 379 | ||
| 380 | /* | ||
| 381 | * The extents in the source inode could still contain speculative | ||
| 382 | * preallocation beyond EOF (e.g. the file is open but not modified | ||
| 383 | * while defrag is in progress). In that case, we need to copy over the | ||
| 384 | * number of delalloc blocks the data fork in the source inode is | ||
| 385 | * tracking beyond EOF so that when the fork is truncated away when the | ||
| 386 | * temporary inode is unlinked we don't underrun the i_delayed_blks | ||
| 387 | * counter on that inode. | ||
| 388 | */ | ||
| 389 | ASSERT(tip->i_delayed_blks == 0); | ||
| 390 | tip->i_delayed_blks = ip->i_delayed_blks; | ||
| 391 | ip->i_delayed_blks = 0; | ||
| 392 | |||
| 380 | ilf_fields = XFS_ILOG_CORE; | 393 | ilf_fields = XFS_ILOG_CORE; |
| 381 | 394 | ||
| 382 | switch(ip->i_d.di_format) { | 395 | switch(ip->i_d.di_format) { |
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index ed9990267661..c78cc6a3d87c 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c | |||
| @@ -58,6 +58,7 @@ xfs_error_trap(int e) | |||
| 58 | int xfs_etest[XFS_NUM_INJECT_ERROR]; | 58 | int xfs_etest[XFS_NUM_INJECT_ERROR]; |
| 59 | int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; | 59 | int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; |
| 60 | char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; | 60 | char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; |
| 61 | int xfs_error_test_active; | ||
| 61 | 62 | ||
| 62 | int | 63 | int |
| 63 | xfs_error_test(int error_tag, int *fsidp, char *expression, | 64 | xfs_error_test(int error_tag, int *fsidp, char *expression, |
| @@ -108,6 +109,7 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp) | |||
| 108 | len = strlen(mp->m_fsname); | 109 | len = strlen(mp->m_fsname); |
| 109 | xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP); | 110 | xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP); |
| 110 | strcpy(xfs_etest_fsname[i], mp->m_fsname); | 111 | strcpy(xfs_etest_fsname[i], mp->m_fsname); |
| 112 | xfs_error_test_active++; | ||
| 111 | return 0; | 113 | return 0; |
| 112 | } | 114 | } |
| 113 | } | 115 | } |
| @@ -137,6 +139,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud) | |||
| 137 | xfs_etest_fsid[i] = 0LL; | 139 | xfs_etest_fsid[i] = 0LL; |
| 138 | kmem_free(xfs_etest_fsname[i]); | 140 | kmem_free(xfs_etest_fsname[i]); |
| 139 | xfs_etest_fsname[i] = NULL; | 141 | xfs_etest_fsname[i] = NULL; |
| 142 | xfs_error_test_active--; | ||
| 140 | } | 143 | } |
| 141 | } | 144 | } |
| 142 | 145 | ||
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index c2c1a072bb82..f338847f80b8 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h | |||
| @@ -127,13 +127,14 @@ extern void xfs_corruption_error(const char *tag, int level, | |||
| 127 | #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT | 127 | #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT |
| 128 | 128 | ||
| 129 | #ifdef DEBUG | 129 | #ifdef DEBUG |
| 130 | extern int xfs_error_test_active; | ||
| 130 | extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); | 131 | extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); |
| 131 | 132 | ||
| 132 | #define XFS_NUM_INJECT_ERROR 10 | 133 | #define XFS_NUM_INJECT_ERROR 10 |
| 133 | #define XFS_TEST_ERROR(expr, mp, tag, rf) \ | 134 | #define XFS_TEST_ERROR(expr, mp, tag, rf) \ |
| 134 | ((expr) || \ | 135 | ((expr) || (xfs_error_test_active && \ |
| 135 | xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \ | 136 | xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \ |
| 136 | (rf))) | 137 | (rf)))) |
| 137 | 138 | ||
| 138 | extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); | 139 | extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); |
| 139 | extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); | 140 | extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index c7ac020705df..7c8d30c453c3 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
| @@ -657,18 +657,37 @@ xfs_inode_item_unlock( | |||
| 657 | } | 657 | } |
| 658 | 658 | ||
| 659 | /* | 659 | /* |
| 660 | * This is called to find out where the oldest active copy of the | 660 | * This is called to find out where the oldest active copy of the inode log |
| 661 | * inode log item in the on disk log resides now that the last log | 661 | * item in the on disk log resides now that the last log write of it completed |
| 662 | * write of it completed at the given lsn. Since we always re-log | 662 | * at the given lsn. Since we always re-log all dirty data in an inode, the |
| 663 | * all dirty data in an inode, the latest copy in the on disk log | 663 | * latest copy in the on disk log is the only one that matters. Therefore, |
| 664 | * is the only one that matters. Therefore, simply return the | 664 | * simply return the given lsn. |
| 665 | * given lsn. | 665 | * |
| 666 | * If the inode has been marked stale because the cluster is being freed, we | ||
| 667 | * don't want to (re-)insert this inode into the AIL. There is a race condition | ||
| 668 | * where the cluster buffer may be unpinned before the inode is inserted into | ||
| 669 | * the AIL during transaction committed processing. If the buffer is unpinned | ||
| 670 | * before the inode item has been committed and inserted, then it is possible | ||
| 671 | * for the buffer to be written and IO completions before the inode is inserted | ||
| 672 | * into the AIL. In that case, we'd be inserting a clean, stale inode into the | ||
| 673 | * AIL which will never get removed. It will, however, get reclaimed which | ||
| 674 | * triggers an assert in xfs_inode_free() complaining about freein an inode | ||
| 675 | * still in the AIL. | ||
| 676 | * | ||
| 677 | * To avoid this, return a lower LSN than the one passed in so that the | ||
| 678 | * transaction committed code will not move the inode forward in the AIL but | ||
| 679 | * will still unpin it properly. | ||
| 666 | */ | 680 | */ |
| 667 | STATIC xfs_lsn_t | 681 | STATIC xfs_lsn_t |
| 668 | xfs_inode_item_committed( | 682 | xfs_inode_item_committed( |
| 669 | struct xfs_log_item *lip, | 683 | struct xfs_log_item *lip, |
| 670 | xfs_lsn_t lsn) | 684 | xfs_lsn_t lsn) |
| 671 | { | 685 | { |
| 686 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | ||
| 687 | struct xfs_inode *ip = iip->ili_inode; | ||
| 688 | |||
| 689 | if (xfs_iflags_test(ip, XFS_ISTALE)) | ||
| 690 | return lsn - 1; | ||
| 672 | return lsn; | 691 | return lsn; |
| 673 | } | 692 | } |
| 674 | 693 | ||
