diff options
Diffstat (limited to 'fs')
52 files changed, 1010 insertions, 450 deletions
diff --git a/fs/Makefile b/fs/Makefile index 2168c902d5ca..d9f8afe6f0c4 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
| @@ -81,8 +81,6 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ | |||
| 81 | obj-$(CONFIG_CODA_FS) += coda/ | 81 | obj-$(CONFIG_CODA_FS) += coda/ |
| 82 | obj-$(CONFIG_MINIX_FS) += minix/ | 82 | obj-$(CONFIG_MINIX_FS) += minix/ |
| 83 | obj-$(CONFIG_FAT_FS) += fat/ | 83 | obj-$(CONFIG_FAT_FS) += fat/ |
| 84 | obj-$(CONFIG_MSDOS_FS) += msdos/ | ||
| 85 | obj-$(CONFIG_VFAT_FS) += vfat/ | ||
| 86 | obj-$(CONFIG_BFS_FS) += bfs/ | 84 | obj-$(CONFIG_BFS_FS) += bfs/ |
| 87 | obj-$(CONFIG_ISO9660_FS) += isofs/ | 85 | obj-$(CONFIG_ISO9660_FS) += isofs/ |
| 88 | obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ | 86 | obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 625abf5422e2..33bf8cbfd051 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
| @@ -128,9 +128,10 @@ static inline void free_dev_ioctl(struct autofs_dev_ioctl *param) | |||
| 128 | */ | 128 | */ |
| 129 | static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param) | 129 | static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param) |
| 130 | { | 130 | { |
| 131 | int err = -EINVAL; | 131 | int err; |
| 132 | 132 | ||
| 133 | if (check_dev_ioctl_version(cmd, param)) { | 133 | err = check_dev_ioctl_version(cmd, param); |
| 134 | if (err) { | ||
| 134 | AUTOFS_WARN("invalid device control module version " | 135 | AUTOFS_WARN("invalid device control module version " |
| 135 | "supplied for cmd(0x%08x)", cmd); | 136 | "supplied for cmd(0x%08x)", cmd); |
| 136 | goto out; | 137 | goto out; |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index cde2f8e8935a..4b6fb3f628c0 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
| @@ -56,12 +56,23 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) | |||
| 56 | mntget(mnt); | 56 | mntget(mnt); |
| 57 | dget(dentry); | 57 | dget(dentry); |
| 58 | 58 | ||
| 59 | if (!autofs4_follow_mount(&mnt, &dentry)) | 59 | if (!follow_down(&mnt, &dentry)) |
| 60 | goto done; | 60 | goto done; |
| 61 | 61 | ||
| 62 | /* This is an autofs submount, we can't expire it */ | 62 | if (is_autofs4_dentry(dentry)) { |
| 63 | if (is_autofs4_dentry(dentry)) | 63 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
| 64 | goto done; | 64 | |
| 65 | /* This is an autofs submount, we can't expire it */ | ||
| 66 | if (sbi->type == AUTOFS_TYPE_INDIRECT) | ||
| 67 | goto done; | ||
| 68 | |||
| 69 | /* | ||
| 70 | * Otherwise it's an offset mount and we need to check | ||
| 71 | * if we can umount its mount, if there is one. | ||
| 72 | */ | ||
| 73 | if (!d_mountpoint(dentry)) | ||
| 74 | goto done; | ||
| 75 | } | ||
| 65 | 76 | ||
| 66 | /* Update the expiry counter if fs is busy */ | 77 | /* Update the expiry counter if fs is busy */ |
| 67 | if (!may_umount_tree(mnt)) { | 78 | if (!may_umount_tree(mnt)) { |
diff --git a/fs/block_dev.c b/fs/block_dev.c index 88a776fa0ef6..db831efbdbbd 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -986,7 +986,6 @@ static int __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part); | |||
| 986 | static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | 986 | static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) |
| 987 | { | 987 | { |
| 988 | struct gendisk *disk; | 988 | struct gendisk *disk; |
| 989 | struct hd_struct *part = NULL; | ||
| 990 | int ret; | 989 | int ret; |
| 991 | int partno; | 990 | int partno; |
| 992 | int perm = 0; | 991 | int perm = 0; |
| @@ -1004,24 +1003,25 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
| 1004 | return ret; | 1003 | return ret; |
| 1005 | } | 1004 | } |
| 1006 | 1005 | ||
| 1007 | ret = -ENXIO; | ||
| 1008 | |||
| 1009 | lock_kernel(); | 1006 | lock_kernel(); |
| 1010 | 1007 | ||
| 1008 | ret = -ENXIO; | ||
| 1011 | disk = get_gendisk(bdev->bd_dev, &partno); | 1009 | disk = get_gendisk(bdev->bd_dev, &partno); |
| 1012 | if (!disk) | 1010 | if (!disk) |
| 1013 | goto out_unlock_kernel; | 1011 | goto out_unlock_kernel; |
| 1014 | part = disk_get_part(disk, partno); | ||
| 1015 | if (!part) | ||
| 1016 | goto out_unlock_kernel; | ||
| 1017 | 1012 | ||
| 1018 | mutex_lock_nested(&bdev->bd_mutex, for_part); | 1013 | mutex_lock_nested(&bdev->bd_mutex, for_part); |
| 1019 | if (!bdev->bd_openers) { | 1014 | if (!bdev->bd_openers) { |
| 1020 | bdev->bd_disk = disk; | 1015 | bdev->bd_disk = disk; |
| 1021 | bdev->bd_part = part; | ||
| 1022 | bdev->bd_contains = bdev; | 1016 | bdev->bd_contains = bdev; |
| 1023 | if (!partno) { | 1017 | if (!partno) { |
| 1024 | struct backing_dev_info *bdi; | 1018 | struct backing_dev_info *bdi; |
| 1019 | |||
| 1020 | ret = -ENXIO; | ||
| 1021 | bdev->bd_part = disk_get_part(disk, partno); | ||
| 1022 | if (!bdev->bd_part) | ||
| 1023 | goto out_clear; | ||
| 1024 | |||
| 1025 | if (disk->fops->open) { | 1025 | if (disk->fops->open) { |
| 1026 | ret = disk->fops->open(bdev, mode); | 1026 | ret = disk->fops->open(bdev, mode); |
| 1027 | if (ret) | 1027 | if (ret) |
| @@ -1049,18 +1049,17 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
| 1049 | bdev->bd_contains = whole; | 1049 | bdev->bd_contains = whole; |
| 1050 | bdev->bd_inode->i_data.backing_dev_info = | 1050 | bdev->bd_inode->i_data.backing_dev_info = |
| 1051 | whole->bd_inode->i_data.backing_dev_info; | 1051 | whole->bd_inode->i_data.backing_dev_info; |
| 1052 | bdev->bd_part = disk_get_part(disk, partno); | ||
| 1052 | if (!(disk->flags & GENHD_FL_UP) || | 1053 | if (!(disk->flags & GENHD_FL_UP) || |
| 1053 | !part || !part->nr_sects) { | 1054 | !bdev->bd_part || !bdev->bd_part->nr_sects) { |
| 1054 | ret = -ENXIO; | 1055 | ret = -ENXIO; |
| 1055 | goto out_clear; | 1056 | goto out_clear; |
| 1056 | } | 1057 | } |
| 1057 | bd_set_size(bdev, (loff_t)part->nr_sects << 9); | 1058 | bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9); |
| 1058 | } | 1059 | } |
| 1059 | } else { | 1060 | } else { |
| 1060 | disk_put_part(part); | ||
| 1061 | put_disk(disk); | 1061 | put_disk(disk); |
| 1062 | module_put(disk->fops->owner); | 1062 | module_put(disk->fops->owner); |
| 1063 | part = NULL; | ||
| 1064 | disk = NULL; | 1063 | disk = NULL; |
| 1065 | if (bdev->bd_contains == bdev) { | 1064 | if (bdev->bd_contains == bdev) { |
| 1066 | if (bdev->bd_disk->fops->open) { | 1065 | if (bdev->bd_disk->fops->open) { |
| @@ -1080,6 +1079,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
| 1080 | return 0; | 1079 | return 0; |
| 1081 | 1080 | ||
| 1082 | out_clear: | 1081 | out_clear: |
| 1082 | disk_put_part(bdev->bd_part); | ||
| 1083 | bdev->bd_disk = NULL; | 1083 | bdev->bd_disk = NULL; |
| 1084 | bdev->bd_part = NULL; | 1084 | bdev->bd_part = NULL; |
| 1085 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; | 1085 | bdev->bd_inode->i_data.backing_dev_info = &default_backing_dev_info; |
| @@ -1091,7 +1091,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part) | |||
| 1091 | out_unlock_kernel: | 1091 | out_unlock_kernel: |
| 1092 | unlock_kernel(); | 1092 | unlock_kernel(); |
| 1093 | 1093 | ||
| 1094 | disk_put_part(part); | ||
| 1095 | if (disk) | 1094 | if (disk) |
| 1096 | module_put(disk->fops->owner); | 1095 | module_put(disk->fops->owner); |
| 1097 | put_disk(disk); | 1096 | put_disk(disk); |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 8f528ea24c48..8855331b2fba 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
| @@ -4,7 +4,11 @@ Various fixes to make delete of open files behavior more predictable | |||
| 4 | (when delete of an open file fails we mark the file as "delete-on-close" | 4 | (when delete of an open file fails we mark the file as "delete-on-close" |
| 5 | in a way that more servers accept, but only if we can first rename the | 5 | in a way that more servers accept, but only if we can first rename the |
| 6 | file to a temporary name). Add experimental support for more safely | 6 | file to a temporary name). Add experimental support for more safely |
| 7 | handling fcntl(F_SETLEASE). | 7 | handling fcntl(F_SETLEASE). Convert cifs to using blocking tcp |
| 8 | sends, and also let tcp autotune the socket send and receive buffers. | ||
| 9 | This reduces the number of EAGAIN errors returned by TCP/IP in | ||
| 10 | high stress workloads (and the number of retries on socket writes | ||
| 11 | when sending large SMBWriteX requests). | ||
| 8 | 12 | ||
| 9 | Version 1.54 | 13 | Version 1.54 |
| 10 | ------------ | 14 | ------------ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c791e5b5a914..1cb1189f24e0 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -141,6 +141,8 @@ struct TCP_Server_Info { | |||
| 141 | char versionMajor; | 141 | char versionMajor; |
| 142 | char versionMinor; | 142 | char versionMinor; |
| 143 | bool svlocal:1; /* local server or remote */ | 143 | bool svlocal:1; /* local server or remote */ |
| 144 | bool noblocksnd; /* use blocking sendmsg */ | ||
| 145 | bool noautotune; /* do not autotune send buf sizes */ | ||
| 144 | atomic_t socketUseCount; /* number of open cifs sessions on socket */ | 146 | atomic_t socketUseCount; /* number of open cifs sessions on socket */ |
| 145 | atomic_t inFlight; /* number of requests on the wire to server */ | 147 | atomic_t inFlight; /* number of requests on the wire to server */ |
| 146 | #ifdef CONFIG_CIFS_STATS2 | 148 | #ifdef CONFIG_CIFS_STATS2 |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 0cff7fe986e8..6f21ecb85ce5 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -36,7 +36,7 @@ extern void cifs_buf_release(void *); | |||
| 36 | extern struct smb_hdr *cifs_small_buf_get(void); | 36 | extern struct smb_hdr *cifs_small_buf_get(void); |
| 37 | extern void cifs_small_buf_release(void *); | 37 | extern void cifs_small_buf_release(void *); |
| 38 | extern int smb_send(struct socket *, struct smb_hdr *, | 38 | extern int smb_send(struct socket *, struct smb_hdr *, |
| 39 | unsigned int /* length */ , struct sockaddr *); | 39 | unsigned int /* length */ , struct sockaddr *, bool); |
| 40 | extern unsigned int _GetXid(void); | 40 | extern unsigned int _GetXid(void); |
| 41 | extern void _FreeXid(unsigned int); | 41 | extern void _FreeXid(unsigned int); |
| 42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid)); | 42 | #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current->fsuid)); |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 843a85fb8b9a..d5eac48fc415 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -1536,7 +1536,7 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon, | |||
| 1536 | __u32 bytes_sent; | 1536 | __u32 bytes_sent; |
| 1537 | __u16 byte_count; | 1537 | __u16 byte_count; |
| 1538 | 1538 | ||
| 1539 | /* cFYI(1,("write at %lld %d bytes",offset,count));*/ | 1539 | /* cFYI(1, ("write at %lld %d bytes", offset, count));*/ |
| 1540 | if (tcon->ses == NULL) | 1540 | if (tcon->ses == NULL) |
| 1541 | return -ECONNABORTED; | 1541 | return -ECONNABORTED; |
| 1542 | 1542 | ||
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 71b7661e2260..e9f9248cb3fe 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -92,6 +92,8 @@ struct smb_vol { | |||
| 92 | bool seal:1; /* request transport encryption on share */ | 92 | bool seal:1; /* request transport encryption on share */ |
| 93 | bool nodfs:1; /* Do not request DFS, even if available */ | 93 | bool nodfs:1; /* Do not request DFS, even if available */ |
| 94 | bool local_lease:1; /* check leases only on local system, not remote */ | 94 | bool local_lease:1; /* check leases only on local system, not remote */ |
| 95 | bool noblocksnd:1; | ||
| 96 | bool noautotune:1; | ||
| 95 | unsigned int rsize; | 97 | unsigned int rsize; |
| 96 | unsigned int wsize; | 98 | unsigned int wsize; |
| 97 | unsigned int sockopt; | 99 | unsigned int sockopt; |
| @@ -102,9 +104,11 @@ struct smb_vol { | |||
| 102 | static int ipv4_connect(struct sockaddr_in *psin_server, | 104 | static int ipv4_connect(struct sockaddr_in *psin_server, |
| 103 | struct socket **csocket, | 105 | struct socket **csocket, |
| 104 | char *netb_name, | 106 | char *netb_name, |
| 105 | char *server_netb_name); | 107 | char *server_netb_name, |
| 108 | bool noblocksnd, | ||
| 109 | bool nosndbuf); /* ipv6 never set sndbuf size */ | ||
| 106 | static int ipv6_connect(struct sockaddr_in6 *psin_server, | 110 | static int ipv6_connect(struct sockaddr_in6 *psin_server, |
| 107 | struct socket **csocket); | 111 | struct socket **csocket, bool noblocksnd); |
| 108 | 112 | ||
| 109 | 113 | ||
| 110 | /* | 114 | /* |
| @@ -191,12 +195,13 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 191 | try_to_freeze(); | 195 | try_to_freeze(); |
| 192 | if (server->protocolType == IPV6) { | 196 | if (server->protocolType == IPV6) { |
| 193 | rc = ipv6_connect(&server->addr.sockAddr6, | 197 | rc = ipv6_connect(&server->addr.sockAddr6, |
| 194 | &server->ssocket); | 198 | &server->ssocket, server->noautotune); |
| 195 | } else { | 199 | } else { |
| 196 | rc = ipv4_connect(&server->addr.sockAddr, | 200 | rc = ipv4_connect(&server->addr.sockAddr, |
| 197 | &server->ssocket, | 201 | &server->ssocket, |
| 198 | server->workstation_RFC1001_name, | 202 | server->workstation_RFC1001_name, |
| 199 | server->server_RFC1001_name); | 203 | server->server_RFC1001_name, |
| 204 | server->noblocksnd, server->noautotune); | ||
| 200 | } | 205 | } |
| 201 | if (rc) { | 206 | if (rc) { |
| 202 | cFYI(1, ("reconnect error %d", rc)); | 207 | cFYI(1, ("reconnect error %d", rc)); |
| @@ -1192,6 +1197,10 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1192 | /* ignore */ | 1197 | /* ignore */ |
| 1193 | } else if (strnicmp(data, "rw", 2) == 0) { | 1198 | } else if (strnicmp(data, "rw", 2) == 0) { |
| 1194 | vol->rw = true; | 1199 | vol->rw = true; |
| 1200 | } else if (strnicmp(data, "noblocksend", 11) == 0) { | ||
| 1201 | vol->noblocksnd = 1; | ||
| 1202 | } else if (strnicmp(data, "noautotune", 10) == 0) { | ||
| 1203 | vol->noautotune = 1; | ||
| 1195 | } else if ((strnicmp(data, "suid", 4) == 0) || | 1204 | } else if ((strnicmp(data, "suid", 4) == 0) || |
| 1196 | (strnicmp(data, "nosuid", 6) == 0) || | 1205 | (strnicmp(data, "nosuid", 6) == 0) || |
| 1197 | (strnicmp(data, "exec", 4) == 0) || | 1206 | (strnicmp(data, "exec", 4) == 0) || |
| @@ -1518,7 +1527,8 @@ static void rfc1002mangle(char *target, char *source, unsigned int length) | |||
| 1518 | 1527 | ||
| 1519 | static int | 1528 | static int |
| 1520 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | 1529 | ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, |
| 1521 | char *netbios_name, char *target_name) | 1530 | char *netbios_name, char *target_name, |
| 1531 | bool noblocksnd, bool noautotune) | ||
| 1522 | { | 1532 | { |
| 1523 | int rc = 0; | 1533 | int rc = 0; |
| 1524 | int connected = 0; | 1534 | int connected = 0; |
| @@ -1590,11 +1600,16 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1590 | (*csocket)->sk->sk_sndbuf, | 1600 | (*csocket)->sk->sk_sndbuf, |
| 1591 | (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); | 1601 | (*csocket)->sk->sk_rcvbuf, (*csocket)->sk->sk_rcvtimeo)); |
| 1592 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; | 1602 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; |
| 1603 | if (!noblocksnd) | ||
| 1604 | (*csocket)->sk->sk_sndtimeo = 3 * HZ; | ||
| 1605 | |||
| 1593 | /* make the bufsizes depend on wsize/rsize and max requests */ | 1606 | /* make the bufsizes depend on wsize/rsize and max requests */ |
| 1594 | if ((*csocket)->sk->sk_sndbuf < (200 * 1024)) | 1607 | if (noautotune) { |
| 1595 | (*csocket)->sk->sk_sndbuf = 200 * 1024; | 1608 | if ((*csocket)->sk->sk_sndbuf < (200 * 1024)) |
| 1596 | if ((*csocket)->sk->sk_rcvbuf < (140 * 1024)) | 1609 | (*csocket)->sk->sk_sndbuf = 200 * 1024; |
| 1597 | (*csocket)->sk->sk_rcvbuf = 140 * 1024; | 1610 | if ((*csocket)->sk->sk_rcvbuf < (140 * 1024)) |
| 1611 | (*csocket)->sk->sk_rcvbuf = 140 * 1024; | ||
| 1612 | } | ||
| 1598 | 1613 | ||
| 1599 | /* send RFC1001 sessinit */ | 1614 | /* send RFC1001 sessinit */ |
| 1600 | if (psin_server->sin_port == htons(RFC1001_PORT)) { | 1615 | if (psin_server->sin_port == htons(RFC1001_PORT)) { |
| @@ -1631,7 +1646,7 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1631 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ | 1646 | /* sizeof RFC1002_SESSION_REQUEST with no scope */ |
| 1632 | smb_buf->smb_buf_length = 0x81000044; | 1647 | smb_buf->smb_buf_length = 0x81000044; |
| 1633 | rc = smb_send(*csocket, smb_buf, 0x44, | 1648 | rc = smb_send(*csocket, smb_buf, 0x44, |
| 1634 | (struct sockaddr *)psin_server); | 1649 | (struct sockaddr *)psin_server, noblocksnd); |
| 1635 | kfree(ses_init_buf); | 1650 | kfree(ses_init_buf); |
| 1636 | msleep(1); /* RFC1001 layer in at least one server | 1651 | msleep(1); /* RFC1001 layer in at least one server |
| 1637 | requires very short break before negprot | 1652 | requires very short break before negprot |
| @@ -1651,7 +1666,8 @@ ipv4_connect(struct sockaddr_in *psin_server, struct socket **csocket, | |||
| 1651 | } | 1666 | } |
| 1652 | 1667 | ||
| 1653 | static int | 1668 | static int |
| 1654 | ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | 1669 | ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket, |
| 1670 | bool noblocksnd) | ||
| 1655 | { | 1671 | { |
| 1656 | int rc = 0; | 1672 | int rc = 0; |
| 1657 | int connected = 0; | 1673 | int connected = 0; |
| @@ -1720,6 +1736,9 @@ ipv6_connect(struct sockaddr_in6 *psin_server, struct socket **csocket) | |||
| 1720 | the default. sock_setsockopt not used because it expects | 1736 | the default. sock_setsockopt not used because it expects |
| 1721 | user space buffer */ | 1737 | user space buffer */ |
| 1722 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; | 1738 | (*csocket)->sk->sk_rcvtimeo = 7 * HZ; |
| 1739 | if (!noblocksnd) | ||
| 1740 | (*csocket)->sk->sk_sndtimeo = 3 * HZ; | ||
| 1741 | |||
| 1723 | 1742 | ||
| 1724 | return rc; | 1743 | return rc; |
| 1725 | } | 1744 | } |
| @@ -1983,11 +2002,14 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 1983 | cFYI(1, ("attempting ipv6 connect")); | 2002 | cFYI(1, ("attempting ipv6 connect")); |
| 1984 | /* BB should we allow ipv6 on port 139? */ | 2003 | /* BB should we allow ipv6 on port 139? */ |
| 1985 | /* other OS never observed in Wild doing 139 with v6 */ | 2004 | /* other OS never observed in Wild doing 139 with v6 */ |
| 1986 | rc = ipv6_connect(&sin_server6, &csocket); | 2005 | rc = ipv6_connect(&sin_server6, &csocket, |
| 2006 | volume_info.noblocksnd); | ||
| 1987 | } else | 2007 | } else |
| 1988 | rc = ipv4_connect(&sin_server, &csocket, | 2008 | rc = ipv4_connect(&sin_server, &csocket, |
| 1989 | volume_info.source_rfc1001_name, | 2009 | volume_info.source_rfc1001_name, |
| 1990 | volume_info.target_rfc1001_name); | 2010 | volume_info.target_rfc1001_name, |
| 2011 | volume_info.noblocksnd, | ||
| 2012 | volume_info.noautotune); | ||
| 1991 | if (rc < 0) { | 2013 | if (rc < 0) { |
| 1992 | cERROR(1, ("Error connecting to IPv4 socket. " | 2014 | cERROR(1, ("Error connecting to IPv4 socket. " |
| 1993 | "Aborting operation")); | 2015 | "Aborting operation")); |
| @@ -2002,6 +2024,8 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2002 | sock_release(csocket); | 2024 | sock_release(csocket); |
| 2003 | goto out; | 2025 | goto out; |
| 2004 | } else { | 2026 | } else { |
| 2027 | srvTcp->noblocksnd = volume_info.noblocksnd; | ||
| 2028 | srvTcp->noautotune = volume_info.noautotune; | ||
| 2005 | memcpy(&srvTcp->addr.sockAddr, &sin_server, | 2029 | memcpy(&srvTcp->addr.sockAddr, &sin_server, |
| 2006 | sizeof(struct sockaddr_in)); | 2030 | sizeof(struct sockaddr_in)); |
| 2007 | atomic_set(&srvTcp->inFlight, 0); | 2031 | atomic_set(&srvTcp->inFlight, 0); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 62d8bd8f14c0..ead1a3bb0256 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -1824,7 +1824,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
| 1824 | pTcon = cifs_sb->tcon; | 1824 | pTcon = cifs_sb->tcon; |
| 1825 | 1825 | ||
| 1826 | pagevec_init(&lru_pvec, 0); | 1826 | pagevec_init(&lru_pvec, 0); |
| 1827 | cFYI(DBG2, ("rpages: num pages %d", num_pages)); | 1827 | cFYI(DBG2, ("rpages: num pages %d", num_pages)); |
| 1828 | for (i = 0; i < num_pages; ) { | 1828 | for (i = 0; i < num_pages; ) { |
| 1829 | unsigned contig_pages; | 1829 | unsigned contig_pages; |
| 1830 | struct page *tmp_page; | 1830 | struct page *tmp_page; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index d54fa8aeaea9..ff8c68de4a92 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -1361,9 +1361,11 @@ int cifs_rename(struct inode *source_dir, struct dentry *source_dentry, | |||
| 1361 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 1361 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 1362 | 1362 | ||
| 1363 | if (tmprc == 0 && (info_buf_source->UniqueId == | 1363 | if (tmprc == 0 && (info_buf_source->UniqueId == |
| 1364 | info_buf_target->UniqueId)) | 1364 | info_buf_target->UniqueId)) { |
| 1365 | /* same file, POSIX says that this is a noop */ | 1365 | /* same file, POSIX says that this is a noop */ |
| 1366 | rc = 0; | ||
| 1366 | goto cifs_rename_exit; | 1367 | goto cifs_rename_exit; |
| 1368 | } | ||
| 1367 | } /* else ... BB we could add the same check for Windows by | 1369 | } /* else ... BB we could add the same check for Windows by |
| 1368 | checking the UniqueId via FILE_INTERNAL_INFO */ | 1370 | checking the UniqueId via FILE_INTERNAL_INFO */ |
| 1369 | 1371 | ||
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index bf0e6d8e382a..ff8243a8fe3e 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -161,7 +161,7 @@ void DeleteTconOplockQEntries(struct cifsTconInfo *tcon) | |||
| 161 | 161 | ||
| 162 | int | 162 | int |
| 163 | smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | 163 | smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, |
| 164 | unsigned int smb_buf_length, struct sockaddr *sin) | 164 | unsigned int smb_buf_length, struct sockaddr *sin, bool noblocksnd) |
| 165 | { | 165 | { |
| 166 | int rc = 0; | 166 | int rc = 0; |
| 167 | int i = 0; | 167 | int i = 0; |
| @@ -178,7 +178,10 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | |||
| 178 | smb_msg.msg_namelen = sizeof(struct sockaddr); | 178 | smb_msg.msg_namelen = sizeof(struct sockaddr); |
| 179 | smb_msg.msg_control = NULL; | 179 | smb_msg.msg_control = NULL; |
| 180 | smb_msg.msg_controllen = 0; | 180 | smb_msg.msg_controllen = 0; |
| 181 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ | 181 | if (noblocksnd) |
| 182 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; | ||
| 183 | else | ||
| 184 | smb_msg.msg_flags = MSG_NOSIGNAL; | ||
| 182 | 185 | ||
| 183 | /* smb header is converted in header_assemble. bcc and rest of SMB word | 186 | /* smb header is converted in header_assemble. bcc and rest of SMB word |
| 184 | area, and byte area if necessary, is converted to littleendian in | 187 | area, and byte area if necessary, is converted to littleendian in |
| @@ -229,8 +232,8 @@ smb_send(struct socket *ssocket, struct smb_hdr *smb_buffer, | |||
| 229 | } | 232 | } |
| 230 | 233 | ||
| 231 | static int | 234 | static int |
| 232 | smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | 235 | smb_send2(struct TCP_Server_Info *server, struct kvec *iov, int n_vec, |
| 233 | struct sockaddr *sin) | 236 | struct sockaddr *sin, bool noblocksnd) |
| 234 | { | 237 | { |
| 235 | int rc = 0; | 238 | int rc = 0; |
| 236 | int i = 0; | 239 | int i = 0; |
| @@ -240,6 +243,7 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
| 240 | unsigned int total_len; | 243 | unsigned int total_len; |
| 241 | int first_vec = 0; | 244 | int first_vec = 0; |
| 242 | unsigned int smb_buf_length = smb_buffer->smb_buf_length; | 245 | unsigned int smb_buf_length = smb_buffer->smb_buf_length; |
| 246 | struct socket *ssocket = server->ssocket; | ||
| 243 | 247 | ||
| 244 | if (ssocket == NULL) | 248 | if (ssocket == NULL) |
| 245 | return -ENOTSOCK; /* BB eventually add reconnect code here */ | 249 | return -ENOTSOCK; /* BB eventually add reconnect code here */ |
| @@ -248,7 +252,10 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
| 248 | smb_msg.msg_namelen = sizeof(struct sockaddr); | 252 | smb_msg.msg_namelen = sizeof(struct sockaddr); |
| 249 | smb_msg.msg_control = NULL; | 253 | smb_msg.msg_control = NULL; |
| 250 | smb_msg.msg_controllen = 0; | 254 | smb_msg.msg_controllen = 0; |
| 251 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; /* BB add more flags?*/ | 255 | if (noblocksnd) |
| 256 | smb_msg.msg_flags = MSG_DONTWAIT + MSG_NOSIGNAL; | ||
| 257 | else | ||
| 258 | smb_msg.msg_flags = MSG_NOSIGNAL; | ||
| 252 | 259 | ||
| 253 | /* smb header is converted in header_assemble. bcc and rest of SMB word | 260 | /* smb header is converted in header_assemble. bcc and rest of SMB word |
| 254 | area, and byte area if necessary, is converted to littleendian in | 261 | area, and byte area if necessary, is converted to littleendian in |
| @@ -283,8 +290,11 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
| 283 | if (rc < 0) | 290 | if (rc < 0) |
| 284 | break; | 291 | break; |
| 285 | 292 | ||
| 286 | if (rc >= total_len) { | 293 | if (rc == total_len) { |
| 287 | WARN_ON(rc > total_len); | 294 | total_len = 0; |
| 295 | break; | ||
| 296 | } else if (rc > total_len) { | ||
| 297 | cERROR(1, ("sent %d requested %d", rc, total_len)); | ||
| 288 | break; | 298 | break; |
| 289 | } | 299 | } |
| 290 | if (rc == 0) { | 300 | if (rc == 0) { |
| @@ -312,6 +322,16 @@ smb_send2(struct socket *ssocket, struct kvec *iov, int n_vec, | |||
| 312 | i = 0; /* in case we get ENOSPC on the next send */ | 322 | i = 0; /* in case we get ENOSPC on the next send */ |
| 313 | } | 323 | } |
| 314 | 324 | ||
| 325 | if ((total_len > 0) && (total_len != smb_buf_length + 4)) { | ||
| 326 | cFYI(1, ("partial send (%d remaining), terminating session", | ||
| 327 | total_len)); | ||
| 328 | /* If we have only sent part of an SMB then the next SMB | ||
| 329 | could be taken as the remainder of this one. We need | ||
| 330 | to kill the socket so the server throws away the partial | ||
| 331 | SMB */ | ||
| 332 | server->tcpStatus = CifsNeedReconnect; | ||
| 333 | } | ||
| 334 | |||
| 315 | if (rc < 0) { | 335 | if (rc < 0) { |
| 316 | cERROR(1, ("Error %d sending data on socket to server", rc)); | 336 | cERROR(1, ("Error %d sending data on socket to server", rc)); |
| 317 | } else | 337 | } else |
| @@ -518,8 +538,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 518 | #ifdef CONFIG_CIFS_STATS2 | 538 | #ifdef CONFIG_CIFS_STATS2 |
| 519 | atomic_inc(&ses->server->inSend); | 539 | atomic_inc(&ses->server->inSend); |
| 520 | #endif | 540 | #endif |
| 521 | rc = smb_send2(ses->server->ssocket, iov, n_vec, | 541 | rc = smb_send2(ses->server, iov, n_vec, |
| 522 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 542 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
| 543 | ses->server->noblocksnd); | ||
| 523 | #ifdef CONFIG_CIFS_STATS2 | 544 | #ifdef CONFIG_CIFS_STATS2 |
| 524 | atomic_dec(&ses->server->inSend); | 545 | atomic_dec(&ses->server->inSend); |
| 525 | midQ->when_sent = jiffies; | 546 | midQ->when_sent = jiffies; |
| @@ -711,7 +732,8 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 711 | atomic_inc(&ses->server->inSend); | 732 | atomic_inc(&ses->server->inSend); |
| 712 | #endif | 733 | #endif |
| 713 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 734 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
| 714 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 735 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
| 736 | ses->server->noblocksnd); | ||
| 715 | #ifdef CONFIG_CIFS_STATS2 | 737 | #ifdef CONFIG_CIFS_STATS2 |
| 716 | atomic_dec(&ses->server->inSend); | 738 | atomic_dec(&ses->server->inSend); |
| 717 | midQ->when_sent = jiffies; | 739 | midQ->when_sent = jiffies; |
| @@ -851,7 +873,8 @@ send_nt_cancel(struct cifsTconInfo *tcon, struct smb_hdr *in_buf, | |||
| 851 | return rc; | 873 | return rc; |
| 852 | } | 874 | } |
| 853 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 875 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
| 854 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 876 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
| 877 | ses->server->noblocksnd); | ||
| 855 | up(&ses->server->tcpSem); | 878 | up(&ses->server->tcpSem); |
| 856 | return rc; | 879 | return rc; |
| 857 | } | 880 | } |
| @@ -941,7 +964,8 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifsTconInfo *tcon, | |||
| 941 | atomic_inc(&ses->server->inSend); | 964 | atomic_inc(&ses->server->inSend); |
| 942 | #endif | 965 | #endif |
| 943 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, | 966 | rc = smb_send(ses->server->ssocket, in_buf, in_buf->smb_buf_length, |
| 944 | (struct sockaddr *) &(ses->server->addr.sockAddr)); | 967 | (struct sockaddr *) &(ses->server->addr.sockAddr), |
| 968 | ses->server->noblocksnd); | ||
| 945 | #ifdef CONFIG_CIFS_STATS2 | 969 | #ifdef CONFIG_CIFS_STATS2 |
| 946 | atomic_dec(&ses->server->inSend); | 970 | atomic_dec(&ses->server->inSend); |
| 947 | midQ->when_sent = jiffies; | 971 | midQ->when_sent = jiffies; |
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 06db79d05c12..6046239465a1 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
| @@ -1251,6 +1251,7 @@ struct kmem_cache *ecryptfs_header_cache_2; | |||
| 1251 | /** | 1251 | /** |
| 1252 | * ecryptfs_write_headers_virt | 1252 | * ecryptfs_write_headers_virt |
| 1253 | * @page_virt: The virtual address to write the headers to | 1253 | * @page_virt: The virtual address to write the headers to |
| 1254 | * @max: The size of memory allocated at page_virt | ||
| 1254 | * @size: Set to the number of bytes written by this function | 1255 | * @size: Set to the number of bytes written by this function |
| 1255 | * @crypt_stat: The cryptographic context | 1256 | * @crypt_stat: The cryptographic context |
| 1256 | * @ecryptfs_dentry: The eCryptfs dentry | 1257 | * @ecryptfs_dentry: The eCryptfs dentry |
| @@ -1278,7 +1279,8 @@ struct kmem_cache *ecryptfs_header_cache_2; | |||
| 1278 | * | 1279 | * |
| 1279 | * Returns zero on success | 1280 | * Returns zero on success |
| 1280 | */ | 1281 | */ |
| 1281 | static int ecryptfs_write_headers_virt(char *page_virt, size_t *size, | 1282 | static int ecryptfs_write_headers_virt(char *page_virt, size_t max, |
| 1283 | size_t *size, | ||
| 1282 | struct ecryptfs_crypt_stat *crypt_stat, | 1284 | struct ecryptfs_crypt_stat *crypt_stat, |
| 1283 | struct dentry *ecryptfs_dentry) | 1285 | struct dentry *ecryptfs_dentry) |
| 1284 | { | 1286 | { |
| @@ -1296,7 +1298,7 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t *size, | |||
| 1296 | offset += written; | 1298 | offset += written; |
| 1297 | rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat, | 1299 | rc = ecryptfs_generate_key_packet_set((page_virt + offset), crypt_stat, |
| 1298 | ecryptfs_dentry, &written, | 1300 | ecryptfs_dentry, &written, |
| 1299 | PAGE_CACHE_SIZE - offset); | 1301 | max - offset); |
| 1300 | if (rc) | 1302 | if (rc) |
| 1301 | ecryptfs_printk(KERN_WARNING, "Error generating key packet " | 1303 | ecryptfs_printk(KERN_WARNING, "Error generating key packet " |
| 1302 | "set; rc = [%d]\n", rc); | 1304 | "set; rc = [%d]\n", rc); |
| @@ -1368,14 +1370,14 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) | |||
| 1368 | goto out; | 1370 | goto out; |
| 1369 | } | 1371 | } |
| 1370 | /* Released in this function */ | 1372 | /* Released in this function */ |
| 1371 | virt = kzalloc(crypt_stat->num_header_bytes_at_front, GFP_KERNEL); | 1373 | virt = (char *)get_zeroed_page(GFP_KERNEL); |
| 1372 | if (!virt) { | 1374 | if (!virt) { |
| 1373 | printk(KERN_ERR "%s: Out of memory\n", __func__); | 1375 | printk(KERN_ERR "%s: Out of memory\n", __func__); |
| 1374 | rc = -ENOMEM; | 1376 | rc = -ENOMEM; |
| 1375 | goto out; | 1377 | goto out; |
| 1376 | } | 1378 | } |
| 1377 | rc = ecryptfs_write_headers_virt(virt, &size, crypt_stat, | 1379 | rc = ecryptfs_write_headers_virt(virt, PAGE_CACHE_SIZE, &size, |
| 1378 | ecryptfs_dentry); | 1380 | crypt_stat, ecryptfs_dentry); |
| 1379 | if (unlikely(rc)) { | 1381 | if (unlikely(rc)) { |
| 1380 | printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n", | 1382 | printk(KERN_ERR "%s: Error whilst writing headers; rc = [%d]\n", |
| 1381 | __func__, rc); | 1383 | __func__, rc); |
| @@ -1393,8 +1395,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry) | |||
| 1393 | goto out_free; | 1395 | goto out_free; |
| 1394 | } | 1396 | } |
| 1395 | out_free: | 1397 | out_free: |
| 1396 | memset(virt, 0, crypt_stat->num_header_bytes_at_front); | 1398 | free_page((unsigned long)virt); |
| 1397 | kfree(virt); | ||
| 1398 | out: | 1399 | out: |
| 1399 | return rc; | 1400 | return rc; |
| 1400 | } | 1401 | } |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 18eaa78ecb4e..5dec6d1356c4 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
| @@ -281,7 +281,8 @@ void ext3_abort (struct super_block * sb, const char * function, | |||
| 281 | EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS; | 281 | EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS; |
| 282 | sb->s_flags |= MS_RDONLY; | 282 | sb->s_flags |= MS_RDONLY; |
| 283 | EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT; | 283 | EXT3_SB(sb)->s_mount_opt |= EXT3_MOUNT_ABORT; |
| 284 | journal_abort(EXT3_SB(sb)->s_journal, -EIO); | 284 | if (EXT3_SB(sb)->s_journal) |
| 285 | journal_abort(EXT3_SB(sb)->s_journal, -EIO); | ||
| 285 | } | 286 | } |
| 286 | 287 | ||
| 287 | void ext3_warning (struct super_block * sb, const char * function, | 288 | void ext3_warning (struct super_block * sb, const char * function, |
| @@ -390,11 +391,14 @@ static void ext3_put_super (struct super_block * sb) | |||
| 390 | { | 391 | { |
| 391 | struct ext3_sb_info *sbi = EXT3_SB(sb); | 392 | struct ext3_sb_info *sbi = EXT3_SB(sb); |
| 392 | struct ext3_super_block *es = sbi->s_es; | 393 | struct ext3_super_block *es = sbi->s_es; |
| 393 | int i; | 394 | int i, err; |
| 394 | 395 | ||
| 395 | ext3_xattr_put_super(sb); | 396 | ext3_xattr_put_super(sb); |
| 396 | if (journal_destroy(sbi->s_journal) < 0) | 397 | err = journal_destroy(sbi->s_journal); |
| 398 | sbi->s_journal = NULL; | ||
| 399 | if (err < 0) | ||
| 397 | ext3_abort(sb, __func__, "Couldn't clean up the journal"); | 400 | ext3_abort(sb, __func__, "Couldn't clean up the journal"); |
| 401 | |||
| 398 | if (!(sb->s_flags & MS_RDONLY)) { | 402 | if (!(sb->s_flags & MS_RDONLY)) { |
| 399 | EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); | 403 | EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); |
| 400 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 404 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
| @@ -2386,13 +2390,12 @@ static void ext3_write_super (struct super_block * sb) | |||
| 2386 | 2390 | ||
| 2387 | static int ext3_sync_fs(struct super_block *sb, int wait) | 2391 | static int ext3_sync_fs(struct super_block *sb, int wait) |
| 2388 | { | 2392 | { |
| 2389 | tid_t target; | ||
| 2390 | |||
| 2391 | sb->s_dirt = 0; | 2393 | sb->s_dirt = 0; |
| 2392 | if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) { | 2394 | if (wait) |
| 2393 | if (wait) | 2395 | ext3_force_commit(sb); |
| 2394 | log_wait_commit(EXT3_SB(sb)->s_journal, target); | 2396 | else |
| 2395 | } | 2397 | journal_start_commit(EXT3_SB(sb)->s_journal, NULL); |
| 2398 | |||
| 2396 | return 0; | 2399 | return 0; |
| 2397 | } | 2400 | } |
| 2398 | 2401 | ||
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index b9821be709bd..d2003cdc36aa 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -589,21 +589,23 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, | |||
| 589 | return; | 589 | return; |
| 590 | } | 590 | } |
| 591 | 591 | ||
| 592 | int ext4_claim_free_blocks(struct ext4_sb_info *sbi, | 592 | /** |
| 593 | s64 nblocks) | 593 | * ext4_has_free_blocks() |
| 594 | * @sbi: in-core super block structure. | ||
| 595 | * @nblocks: number of needed blocks | ||
| 596 | * | ||
| 597 | * Check if filesystem has nblocks free & available for allocation. | ||
| 598 | * On success return 1, return 0 on failure. | ||
| 599 | */ | ||
| 600 | int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks) | ||
| 594 | { | 601 | { |
| 595 | s64 free_blocks, dirty_blocks; | 602 | s64 free_blocks, dirty_blocks, root_blocks; |
| 596 | s64 root_blocks = 0; | ||
| 597 | struct percpu_counter *fbc = &sbi->s_freeblocks_counter; | 603 | struct percpu_counter *fbc = &sbi->s_freeblocks_counter; |
| 598 | struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter; | 604 | struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter; |
| 599 | 605 | ||
| 600 | free_blocks = percpu_counter_read_positive(fbc); | 606 | free_blocks = percpu_counter_read_positive(fbc); |
| 601 | dirty_blocks = percpu_counter_read_positive(dbc); | 607 | dirty_blocks = percpu_counter_read_positive(dbc); |
| 602 | 608 | root_blocks = ext4_r_blocks_count(sbi->s_es); | |
| 603 | if (!capable(CAP_SYS_RESOURCE) && | ||
| 604 | sbi->s_resuid != current->fsuid && | ||
| 605 | (sbi->s_resgid == 0 || !in_group_p(sbi->s_resgid))) | ||
| 606 | root_blocks = ext4_r_blocks_count(sbi->s_es); | ||
| 607 | 609 | ||
| 608 | if (free_blocks - (nblocks + root_blocks + dirty_blocks) < | 610 | if (free_blocks - (nblocks + root_blocks + dirty_blocks) < |
| 609 | EXT4_FREEBLOCKS_WATERMARK) { | 611 | EXT4_FREEBLOCKS_WATERMARK) { |
| @@ -616,57 +618,32 @@ int ext4_claim_free_blocks(struct ext4_sb_info *sbi, | |||
| 616 | } | 618 | } |
| 617 | } | 619 | } |
| 618 | /* Check whether we have space after | 620 | /* Check whether we have space after |
| 619 | * accounting for current dirty blocks | 621 | * accounting for current dirty blocks & root reserved blocks. |
| 620 | */ | 622 | */ |
| 621 | if (free_blocks < ((root_blocks + nblocks) + dirty_blocks)) | 623 | if (free_blocks >= ((root_blocks + nblocks) + dirty_blocks)) |
| 622 | /* we don't have free space */ | 624 | return 1; |
| 623 | return -ENOSPC; | 625 | |
| 626 | /* Hm, nope. Are (enough) root reserved blocks available? */ | ||
| 627 | if (sbi->s_resuid == current->fsuid || | ||
| 628 | ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) || | ||
| 629 | capable(CAP_SYS_RESOURCE)) { | ||
| 630 | if (free_blocks >= (nblocks + dirty_blocks)) | ||
| 631 | return 1; | ||
| 632 | } | ||
| 624 | 633 | ||
| 625 | /* Add the blocks to nblocks */ | ||
| 626 | percpu_counter_add(dbc, nblocks); | ||
| 627 | return 0; | 634 | return 0; |
| 628 | } | 635 | } |
| 629 | 636 | ||
| 630 | /** | 637 | int ext4_claim_free_blocks(struct ext4_sb_info *sbi, |
| 631 | * ext4_has_free_blocks() | ||
| 632 | * @sbi: in-core super block structure. | ||
| 633 | * @nblocks: number of neeed blocks | ||
| 634 | * | ||
| 635 | * Check if filesystem has free blocks available for allocation. | ||
| 636 | * Return the number of blocks avaible for allocation for this request | ||
| 637 | * On success, return nblocks | ||
| 638 | */ | ||
| 639 | ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi, | ||
| 640 | s64 nblocks) | 638 | s64 nblocks) |
| 641 | { | 639 | { |
| 642 | s64 free_blocks, dirty_blocks; | 640 | if (ext4_has_free_blocks(sbi, nblocks)) { |
| 643 | s64 root_blocks = 0; | 641 | percpu_counter_add(&sbi->s_dirtyblocks_counter, nblocks); |
| 644 | struct percpu_counter *fbc = &sbi->s_freeblocks_counter; | ||
| 645 | struct percpu_counter *dbc = &sbi->s_dirtyblocks_counter; | ||
| 646 | |||
| 647 | free_blocks = percpu_counter_read_positive(fbc); | ||
| 648 | dirty_blocks = percpu_counter_read_positive(dbc); | ||
| 649 | |||
| 650 | if (!capable(CAP_SYS_RESOURCE) && | ||
| 651 | sbi->s_resuid != current->fsuid && | ||
| 652 | (sbi->s_resgid == 0 || !in_group_p(sbi->s_resgid))) | ||
| 653 | root_blocks = ext4_r_blocks_count(sbi->s_es); | ||
| 654 | |||
| 655 | if (free_blocks - (nblocks + root_blocks + dirty_blocks) < | ||
| 656 | EXT4_FREEBLOCKS_WATERMARK) { | ||
| 657 | free_blocks = percpu_counter_sum(fbc); | ||
| 658 | dirty_blocks = percpu_counter_sum(dbc); | ||
| 659 | } | ||
| 660 | if (free_blocks <= (root_blocks + dirty_blocks)) | ||
| 661 | /* we don't have free space */ | ||
| 662 | return 0; | 642 | return 0; |
| 663 | 643 | } else | |
| 664 | if (free_blocks - (root_blocks + dirty_blocks) < nblocks) | 644 | return -ENOSPC; |
| 665 | return free_blocks - (root_blocks + dirty_blocks); | ||
| 666 | return nblocks; | ||
| 667 | } | 645 | } |
| 668 | 646 | ||
| 669 | |||
| 670 | /** | 647 | /** |
| 671 | * ext4_should_retry_alloc() | 648 | * ext4_should_retry_alloc() |
| 672 | * @sb: super block | 649 | * @sb: super block |
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 4880cc3e6727..b0537c827024 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -1003,8 +1003,7 @@ extern ext4_fsblk_t ext4_new_blocks(handle_t *handle, struct inode *inode, | |||
| 1003 | ext4_lblk_t iblock, ext4_fsblk_t goal, | 1003 | ext4_lblk_t iblock, ext4_fsblk_t goal, |
| 1004 | unsigned long *count, int *errp); | 1004 | unsigned long *count, int *errp); |
| 1005 | extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); | 1005 | extern int ext4_claim_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); |
| 1006 | extern ext4_fsblk_t ext4_has_free_blocks(struct ext4_sb_info *sbi, | 1006 | extern int ext4_has_free_blocks(struct ext4_sb_info *sbi, s64 nblocks); |
| 1007 | s64 nblocks); | ||
| 1008 | extern void ext4_free_blocks(handle_t *handle, struct inode *inode, | 1007 | extern void ext4_free_blocks(handle_t *handle, struct inode *inode, |
| 1009 | ext4_fsblk_t block, unsigned long count, int metadata); | 1008 | ext4_fsblk_t block, unsigned long count, int metadata); |
| 1010 | extern void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb, | 1009 | extern void ext4_free_blocks_sb(handle_t *handle, struct super_block *sb, |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index fe34d74cfb19..2a117e286e54 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
| @@ -718,6 +718,8 @@ got: | |||
| 718 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); | 718 | gdp->bg_flags &= cpu_to_le16(~EXT4_BG_BLOCK_UNINIT); |
| 719 | free = ext4_free_blocks_after_init(sb, group, gdp); | 719 | free = ext4_free_blocks_after_init(sb, group, gdp); |
| 720 | gdp->bg_free_blocks_count = cpu_to_le16(free); | 720 | gdp->bg_free_blocks_count = cpu_to_le16(free); |
| 721 | gdp->bg_checksum = ext4_group_desc_csum(sbi, group, | ||
| 722 | gdp); | ||
| 721 | } | 723 | } |
| 722 | spin_unlock(sb_bgl_lock(sbi, group)); | 724 | spin_unlock(sb_bgl_lock(sbi, group)); |
| 723 | 725 | ||
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8dbf6953845b..be21a5ae33cb 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -2329,6 +2329,8 @@ static int ext4_da_writepage(struct page *page, | |||
| 2329 | unlock_page(page); | 2329 | unlock_page(page); |
| 2330 | return 0; | 2330 | return 0; |
| 2331 | } | 2331 | } |
| 2332 | /* now mark the buffer_heads as dirty and uptodate */ | ||
| 2333 | block_commit_write(page, 0, PAGE_CACHE_SIZE); | ||
| 2332 | } | 2334 | } |
| 2333 | 2335 | ||
| 2334 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) | 2336 | if (test_opt(inode->i_sb, NOBH) && ext4_should_writeback_data(inode)) |
| @@ -4580,9 +4582,10 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks, | |||
| 4580 | static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) | 4582 | static int ext4_index_trans_blocks(struct inode *inode, int nrblocks, int chunk) |
| 4581 | { | 4583 | { |
| 4582 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) | 4584 | if (!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)) |
| 4583 | return ext4_indirect_trans_blocks(inode, nrblocks, 0); | 4585 | return ext4_indirect_trans_blocks(inode, nrblocks, chunk); |
| 4584 | return ext4_ext_index_trans_blocks(inode, nrblocks, 0); | 4586 | return ext4_ext_index_trans_blocks(inode, nrblocks, chunk); |
| 4585 | } | 4587 | } |
| 4588 | |||
| 4586 | /* | 4589 | /* |
| 4587 | * Account for index blocks, block groups bitmaps and block group | 4590 | * Account for index blocks, block groups bitmaps and block group |
| 4588 | * descriptor blocks if modify datablocks and index blocks | 4591 | * descriptor blocks if modify datablocks and index blocks |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index dfe17a134052..444ad998f72e 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -4441,6 +4441,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | |||
| 4441 | else if (block >= (entry->start_blk + entry->count)) | 4441 | else if (block >= (entry->start_blk + entry->count)) |
| 4442 | n = &(*n)->rb_right; | 4442 | n = &(*n)->rb_right; |
| 4443 | else { | 4443 | else { |
| 4444 | ext4_unlock_group(sb, group); | ||
| 4444 | ext4_error(sb, __func__, | 4445 | ext4_error(sb, __func__, |
| 4445 | "Double free of blocks %d (%d %d)\n", | 4446 | "Double free of blocks %d (%d %d)\n", |
| 4446 | block, entry->start_blk, entry->count); | 4447 | block, entry->start_blk, entry->count); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index bdddea14e782..e4a241c65dbe 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -333,7 +333,8 @@ void ext4_abort(struct super_block *sb, const char *function, | |||
| 333 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; | 333 | EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; |
| 334 | sb->s_flags |= MS_RDONLY; | 334 | sb->s_flags |= MS_RDONLY; |
| 335 | EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT; | 335 | EXT4_SB(sb)->s_mount_opt |= EXT4_MOUNT_ABORT; |
| 336 | jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); | 336 | if (EXT4_SB(sb)->s_journal) |
| 337 | jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); | ||
| 337 | } | 338 | } |
| 338 | 339 | ||
| 339 | void ext4_warning(struct super_block *sb, const char *function, | 340 | void ext4_warning(struct super_block *sb, const char *function, |
| @@ -442,14 +443,16 @@ static void ext4_put_super(struct super_block *sb) | |||
| 442 | { | 443 | { |
| 443 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 444 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 444 | struct ext4_super_block *es = sbi->s_es; | 445 | struct ext4_super_block *es = sbi->s_es; |
| 445 | int i; | 446 | int i, err; |
| 446 | 447 | ||
| 447 | ext4_mb_release(sb); | 448 | ext4_mb_release(sb); |
| 448 | ext4_ext_release(sb); | 449 | ext4_ext_release(sb); |
| 449 | ext4_xattr_put_super(sb); | 450 | ext4_xattr_put_super(sb); |
| 450 | if (jbd2_journal_destroy(sbi->s_journal) < 0) | 451 | err = jbd2_journal_destroy(sbi->s_journal); |
| 451 | ext4_abort(sb, __func__, "Couldn't clean up the journal"); | ||
| 452 | sbi->s_journal = NULL; | 452 | sbi->s_journal = NULL; |
| 453 | if (err < 0) | ||
| 454 | ext4_abort(sb, __func__, "Couldn't clean up the journal"); | ||
| 455 | |||
| 453 | if (!(sb->s_flags & MS_RDONLY)) { | 456 | if (!(sb->s_flags & MS_RDONLY)) { |
| 454 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 457 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
| 455 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 458 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
| @@ -1455,9 +1458,8 @@ static int ext4_fill_flex_info(struct super_block *sb) | |||
| 1455 | 1458 | ||
| 1456 | /* We allocate both existing and potentially added groups */ | 1459 | /* We allocate both existing and potentially added groups */ |
| 1457 | flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + | 1460 | flex_group_count = ((sbi->s_groups_count + groups_per_flex - 1) + |
| 1458 | ((sbi->s_es->s_reserved_gdt_blocks +1 ) << | 1461 | ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << |
| 1459 | EXT4_DESC_PER_BLOCK_BITS(sb))) / | 1462 | EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex; |
| 1460 | groups_per_flex; | ||
| 1461 | sbi->s_flex_groups = kzalloc(flex_group_count * | 1463 | sbi->s_flex_groups = kzalloc(flex_group_count * |
| 1462 | sizeof(struct flex_groups), GFP_KERNEL); | 1464 | sizeof(struct flex_groups), GFP_KERNEL); |
| 1463 | if (sbi->s_flex_groups == NULL) { | 1465 | if (sbi->s_flex_groups == NULL) { |
| @@ -2882,12 +2884,9 @@ int ext4_force_commit(struct super_block *sb) | |||
| 2882 | /* | 2884 | /* |
| 2883 | * Ext4 always journals updates to the superblock itself, so we don't | 2885 | * Ext4 always journals updates to the superblock itself, so we don't |
| 2884 | * have to propagate any other updates to the superblock on disk at this | 2886 | * have to propagate any other updates to the superblock on disk at this |
| 2885 | * point. Just start an async writeback to get the buffers on their way | 2887 | * point. (We can probably nuke this function altogether, and remove |
| 2886 | * to the disk. | 2888 | * any mention to sb->s_dirt in all of fs/ext4; eventual cleanup...) |
| 2887 | * | ||
| 2888 | * This implicitly triggers the writebehind on sync(). | ||
| 2889 | */ | 2889 | */ |
| 2890 | |||
| 2891 | static void ext4_write_super(struct super_block *sb) | 2890 | static void ext4_write_super(struct super_block *sb) |
| 2892 | { | 2891 | { |
| 2893 | if (mutex_trylock(&sb->s_lock) != 0) | 2892 | if (mutex_trylock(&sb->s_lock) != 0) |
| @@ -2897,15 +2896,15 @@ static void ext4_write_super(struct super_block *sb) | |||
| 2897 | 2896 | ||
| 2898 | static int ext4_sync_fs(struct super_block *sb, int wait) | 2897 | static int ext4_sync_fs(struct super_block *sb, int wait) |
| 2899 | { | 2898 | { |
| 2900 | tid_t target; | 2899 | int ret = 0; |
| 2901 | 2900 | ||
| 2902 | trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait); | 2901 | trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait); |
| 2903 | sb->s_dirt = 0; | 2902 | sb->s_dirt = 0; |
| 2904 | if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, &target)) { | 2903 | if (wait) |
| 2905 | if (wait) | 2904 | ret = ext4_force_commit(sb); |
| 2906 | jbd2_log_wait_commit(EXT4_SB(sb)->s_journal, target); | 2905 | else |
| 2907 | } | 2906 | jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, NULL); |
| 2908 | return 0; | 2907 | return ret; |
| 2909 | } | 2908 | } |
| 2910 | 2909 | ||
| 2911 | /* | 2910 | /* |
diff --git a/fs/fat/Makefile b/fs/fat/Makefile index bfb5f06cf2c8..e06190322c1c 100644 --- a/fs/fat/Makefile +++ b/fs/fat/Makefile | |||
| @@ -3,5 +3,9 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_FAT_FS) += fat.o | 5 | obj-$(CONFIG_FAT_FS) += fat.o |
| 6 | obj-$(CONFIG_VFAT_FS) += vfat.o | ||
| 7 | obj-$(CONFIG_MSDOS_FS) += msdos.o | ||
| 6 | 8 | ||
| 7 | fat-objs := cache.o dir.o fatent.o file.o inode.o misc.o | 9 | fat-y := cache.o dir.o fatent.o file.o inode.o misc.o |
| 10 | vfat-y := namei_vfat.o | ||
| 11 | msdos-y := namei_msdos.o | ||
diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 3222f51c41cf..b42602298087 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
| 12 | #include <linux/msdos_fs.h> | ||
| 13 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
| 13 | #include "fat.h" | ||
| 14 | 14 | ||
| 15 | /* this must be > 0. */ | 15 | /* this must be > 0. */ |
| 16 | #define FAT_MAX_CACHE 8 | 16 | #define FAT_MAX_CACHE 8 |
| @@ -293,10 +293,12 @@ static int fat_bmap_cluster(struct inode *inode, int cluster) | |||
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, | 295 | int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, |
| 296 | unsigned long *mapped_blocks) | 296 | unsigned long *mapped_blocks, int create) |
| 297 | { | 297 | { |
| 298 | struct super_block *sb = inode->i_sb; | 298 | struct super_block *sb = inode->i_sb; |
| 299 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 299 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
| 300 | const unsigned long blocksize = sb->s_blocksize; | ||
| 301 | const unsigned char blocksize_bits = sb->s_blocksize_bits; | ||
| 300 | sector_t last_block; | 302 | sector_t last_block; |
| 301 | int cluster, offset; | 303 | int cluster, offset; |
| 302 | 304 | ||
| @@ -309,10 +311,21 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, | |||
| 309 | } | 311 | } |
| 310 | return 0; | 312 | return 0; |
| 311 | } | 313 | } |
| 312 | last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1)) | 314 | |
| 313 | >> sb->s_blocksize_bits; | 315 | last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; |
| 314 | if (sector >= last_block) | 316 | if (sector >= last_block) { |
| 315 | return 0; | 317 | if (!create) |
| 318 | return 0; | ||
| 319 | |||
| 320 | /* | ||
| 321 | * ->mmu_private can access on only allocation path. | ||
| 322 | * (caller must hold ->i_mutex) | ||
| 323 | */ | ||
| 324 | last_block = (MSDOS_I(inode)->mmu_private + (blocksize - 1)) | ||
| 325 | >> blocksize_bits; | ||
| 326 | if (sector >= last_block) | ||
| 327 | return 0; | ||
| 328 | } | ||
| 316 | 329 | ||
| 317 | cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits); | 330 | cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits); |
| 318 | offset = sector & (sbi->sec_per_clus - 1); | 331 | offset = sector & (sbi->sec_per_clus - 1); |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index bae1c3292522..67e058357098 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
| @@ -16,11 +16,11 @@ | |||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
| 19 | #include <linux/msdos_fs.h> | ||
| 20 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
| 21 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
| 22 | #include <linux/compat.h> | 21 | #include <linux/compat.h> |
| 23 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
| 23 | #include "fat.h" | ||
| 24 | 24 | ||
| 25 | static inline loff_t fat_make_i_pos(struct super_block *sb, | 25 | static inline loff_t fat_make_i_pos(struct super_block *sb, |
| 26 | struct buffer_head *bh, | 26 | struct buffer_head *bh, |
| @@ -77,7 +77,7 @@ next: | |||
| 77 | 77 | ||
| 78 | *bh = NULL; | 78 | *bh = NULL; |
| 79 | iblock = *pos >> sb->s_blocksize_bits; | 79 | iblock = *pos >> sb->s_blocksize_bits; |
| 80 | err = fat_bmap(dir, iblock, &phys, &mapped_blocks); | 80 | err = fat_bmap(dir, iblock, &phys, &mapped_blocks, 0); |
| 81 | if (err || !phys) | 81 | if (err || !phys) |
| 82 | return -1; /* beyond EOF or error */ | 82 | return -1; /* beyond EOF or error */ |
| 83 | 83 | ||
| @@ -86,7 +86,7 @@ next: | |||
| 86 | *bh = sb_bread(sb, phys); | 86 | *bh = sb_bread(sb, phys); |
| 87 | if (*bh == NULL) { | 87 | if (*bh == NULL) { |
| 88 | printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n", | 88 | printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n", |
| 89 | (unsigned long long)phys); | 89 | (llu)phys); |
| 90 | /* skip this block */ | 90 | /* skip this block */ |
| 91 | *pos = (iblock + 1) << sb->s_blocksize_bits; | 91 | *pos = (iblock + 1) << sb->s_blocksize_bits; |
| 92 | goto next; | 92 | goto next; |
| @@ -373,9 +373,10 @@ parse_record: | |||
| 373 | if (de->attr == ATTR_EXT) { | 373 | if (de->attr == ATTR_EXT) { |
| 374 | int status = fat_parse_long(inode, &cpos, &bh, &de, | 374 | int status = fat_parse_long(inode, &cpos, &bh, &de, |
| 375 | &unicode, &nr_slots); | 375 | &unicode, &nr_slots); |
| 376 | if (status < 0) | 376 | if (status < 0) { |
| 377 | return status; | 377 | err = status; |
| 378 | else if (status == PARSE_INVALID) | 378 | goto end_of_dir; |
| 379 | } else if (status == PARSE_INVALID) | ||
| 379 | continue; | 380 | continue; |
| 380 | else if (status == PARSE_NOT_LONGNAME) | 381 | else if (status == PARSE_NOT_LONGNAME) |
| 381 | goto parse_record; | 382 | goto parse_record; |
| @@ -832,6 +833,7 @@ static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd, | |||
| 832 | #endif /* CONFIG_COMPAT */ | 833 | #endif /* CONFIG_COMPAT */ |
| 833 | 834 | ||
| 834 | const struct file_operations fat_dir_operations = { | 835 | const struct file_operations fat_dir_operations = { |
| 836 | .llseek = generic_file_llseek, | ||
| 835 | .read = generic_read_dir, | 837 | .read = generic_read_dir, |
| 836 | .readdir = fat_readdir, | 838 | .readdir = fat_readdir, |
| 837 | .ioctl = fat_dir_ioctl, | 839 | .ioctl = fat_dir_ioctl, |
| @@ -1089,6 +1091,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts) | |||
| 1089 | struct msdos_dir_entry *de; | 1091 | struct msdos_dir_entry *de; |
| 1090 | sector_t blknr; | 1092 | sector_t blknr; |
| 1091 | __le16 date, time; | 1093 | __le16 date, time; |
| 1094 | u8 time_cs; | ||
| 1092 | int err, cluster; | 1095 | int err, cluster; |
| 1093 | 1096 | ||
| 1094 | err = fat_alloc_clusters(dir, &cluster, 1); | 1097 | err = fat_alloc_clusters(dir, &cluster, 1); |
| @@ -1102,7 +1105,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts) | |||
| 1102 | goto error_free; | 1105 | goto error_free; |
| 1103 | } | 1106 | } |
| 1104 | 1107 | ||
| 1105 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); | 1108 | fat_time_unix2fat(sbi, ts, &time, &date, &time_cs); |
| 1106 | 1109 | ||
| 1107 | de = (struct msdos_dir_entry *)bhs[0]->b_data; | 1110 | de = (struct msdos_dir_entry *)bhs[0]->b_data; |
| 1108 | /* filling the new directory slots ("." and ".." entries) */ | 1111 | /* filling the new directory slots ("." and ".." entries) */ |
| @@ -1112,13 +1115,14 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts) | |||
| 1112 | de[0].lcase = de[1].lcase = 0; | 1115 | de[0].lcase = de[1].lcase = 0; |
| 1113 | de[0].time = de[1].time = time; | 1116 | de[0].time = de[1].time = time; |
| 1114 | de[0].date = de[1].date = date; | 1117 | de[0].date = de[1].date = date; |
| 1115 | de[0].ctime_cs = de[1].ctime_cs = 0; | ||
| 1116 | if (sbi->options.isvfat) { | 1118 | if (sbi->options.isvfat) { |
| 1117 | /* extra timestamps */ | 1119 | /* extra timestamps */ |
| 1118 | de[0].ctime = de[1].ctime = time; | 1120 | de[0].ctime = de[1].ctime = time; |
| 1121 | de[0].ctime_cs = de[1].ctime_cs = time_cs; | ||
| 1119 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date; | 1122 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date; |
| 1120 | } else { | 1123 | } else { |
| 1121 | de[0].ctime = de[1].ctime = 0; | 1124 | de[0].ctime = de[1].ctime = 0; |
| 1125 | de[0].ctime_cs = de[1].ctime_cs = 0; | ||
| 1122 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0; | 1126 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0; |
| 1123 | } | 1127 | } |
| 1124 | de[0].start = cpu_to_le16(cluster); | 1128 | de[0].start = cpu_to_le16(cluster); |
diff --git a/fs/fat/fat.h b/fs/fat/fat.h new file mode 100644 index 000000000000..ea440d65819c --- /dev/null +++ b/fs/fat/fat.h | |||
| @@ -0,0 +1,329 @@ | |||
| 1 | #ifndef _FAT_H | ||
| 2 | #define _FAT_H | ||
| 3 | |||
| 4 | #include <linux/buffer_head.h> | ||
| 5 | #include <linux/string.h> | ||
| 6 | #include <linux/nls.h> | ||
| 7 | #include <linux/fs.h> | ||
| 8 | #include <linux/mutex.h> | ||
| 9 | #include <linux/msdos_fs.h> | ||
| 10 | |||
| 11 | /* | ||
| 12 | * vfat shortname flags | ||
| 13 | */ | ||
| 14 | #define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ | ||
| 15 | #define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ | ||
| 16 | #define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ | ||
| 17 | #define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ | ||
| 18 | #define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ | ||
| 19 | |||
| 20 | struct fat_mount_options { | ||
| 21 | uid_t fs_uid; | ||
| 22 | gid_t fs_gid; | ||
| 23 | unsigned short fs_fmask; | ||
| 24 | unsigned short fs_dmask; | ||
| 25 | unsigned short codepage; /* Codepage for shortname conversions */ | ||
| 26 | char *iocharset; /* Charset used for filename input/display */ | ||
| 27 | unsigned short shortname; /* flags for shortname display/create rule */ | ||
| 28 | unsigned char name_check; /* r = relaxed, n = normal, s = strict */ | ||
| 29 | unsigned short allow_utime;/* permission for setting the [am]time */ | ||
| 30 | unsigned quiet:1, /* set = fake successful chmods and chowns */ | ||
| 31 | showexec:1, /* set = only set x bit for com/exe/bat */ | ||
| 32 | sys_immutable:1, /* set = system files are immutable */ | ||
| 33 | dotsOK:1, /* set = hidden and system files are named '.filename' */ | ||
| 34 | isvfat:1, /* 0=no vfat long filename support, 1=vfat support */ | ||
| 35 | utf8:1, /* Use of UTF-8 character set (Default) */ | ||
| 36 | unicode_xlate:1, /* create escape sequences for unhandled Unicode */ | ||
| 37 | numtail:1, /* Does first alias have a numeric '~1' type tail? */ | ||
| 38 | flush:1, /* write things quickly */ | ||
| 39 | nocase:1, /* Does this need case conversion? 0=need case conversion*/ | ||
| 40 | usefree:1, /* Use free_clusters for FAT32 */ | ||
| 41 | tz_utc:1, /* Filesystem timestamps are in UTC */ | ||
| 42 | rodir:1; /* allow ATTR_RO for directory */ | ||
| 43 | }; | ||
| 44 | |||
| 45 | #define FAT_HASH_BITS 8 | ||
| 46 | #define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) | ||
| 47 | |||
| 48 | /* | ||
| 49 | * MS-DOS file system in-core superblock data | ||
| 50 | */ | ||
| 51 | struct msdos_sb_info { | ||
| 52 | unsigned short sec_per_clus; /* sectors/cluster */ | ||
| 53 | unsigned short cluster_bits; /* log2(cluster_size) */ | ||
| 54 | unsigned int cluster_size; /* cluster size */ | ||
| 55 | unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */ | ||
| 56 | unsigned short fat_start; | ||
| 57 | unsigned long fat_length; /* FAT start & length (sec.) */ | ||
| 58 | unsigned long dir_start; | ||
| 59 | unsigned short dir_entries; /* root dir start & entries */ | ||
| 60 | unsigned long data_start; /* first data sector */ | ||
| 61 | unsigned long max_cluster; /* maximum cluster number */ | ||
| 62 | unsigned long root_cluster; /* first cluster of the root directory */ | ||
| 63 | unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ | ||
| 64 | struct mutex fat_lock; | ||
| 65 | unsigned int prev_free; /* previously allocated cluster number */ | ||
| 66 | unsigned int free_clusters; /* -1 if undefined */ | ||
| 67 | unsigned int free_clus_valid; /* is free_clusters valid? */ | ||
| 68 | struct fat_mount_options options; | ||
| 69 | struct nls_table *nls_disk; /* Codepage used on disk */ | ||
| 70 | struct nls_table *nls_io; /* Charset used for input and display */ | ||
| 71 | const void *dir_ops; /* Opaque; default directory operations */ | ||
| 72 | int dir_per_block; /* dir entries per block */ | ||
| 73 | int dir_per_block_bits; /* log2(dir_per_block) */ | ||
| 74 | |||
| 75 | int fatent_shift; | ||
| 76 | struct fatent_operations *fatent_ops; | ||
| 77 | |||
| 78 | spinlock_t inode_hash_lock; | ||
| 79 | struct hlist_head inode_hashtable[FAT_HASH_SIZE]; | ||
| 80 | }; | ||
| 81 | |||
| 82 | #define FAT_CACHE_VALID 0 /* special case for valid cache */ | ||
| 83 | |||
| 84 | /* | ||
| 85 | * MS-DOS file system inode data in memory | ||
| 86 | */ | ||
| 87 | struct msdos_inode_info { | ||
| 88 | spinlock_t cache_lru_lock; | ||
| 89 | struct list_head cache_lru; | ||
| 90 | int nr_caches; | ||
| 91 | /* for avoiding the race between fat_free() and fat_get_cluster() */ | ||
| 92 | unsigned int cache_valid_id; | ||
| 93 | |||
| 94 | /* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */ | ||
| 95 | loff_t mmu_private; /* physically allocated size */ | ||
| 96 | |||
| 97 | int i_start; /* first cluster or 0 */ | ||
| 98 | int i_logstart; /* logical first cluster */ | ||
| 99 | int i_attrs; /* unused attribute bits */ | ||
| 100 | loff_t i_pos; /* on-disk position of directory entry or 0 */ | ||
| 101 | struct hlist_node i_fat_hash; /* hash by i_location */ | ||
| 102 | struct inode vfs_inode; | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct fat_slot_info { | ||
| 106 | loff_t i_pos; /* on-disk position of directory entry */ | ||
| 107 | loff_t slot_off; /* offset for slot or de start */ | ||
| 108 | int nr_slots; /* number of slots + 1(de) in filename */ | ||
| 109 | struct msdos_dir_entry *de; | ||
| 110 | struct buffer_head *bh; | ||
| 111 | }; | ||
| 112 | |||
| 113 | static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) | ||
| 114 | { | ||
| 115 | return sb->s_fs_info; | ||
| 116 | } | ||
| 117 | |||
| 118 | static inline struct msdos_inode_info *MSDOS_I(struct inode *inode) | ||
| 119 | { | ||
| 120 | return container_of(inode, struct msdos_inode_info, vfs_inode); | ||
| 121 | } | ||
| 122 | |||
| 123 | /* | ||
| 124 | * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to | ||
| 125 | * save ATTR_RO instead of ->i_mode. | ||
| 126 | * | ||
| 127 | * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only | ||
| 128 | * bit, it's just used as flag for app. | ||
| 129 | */ | ||
| 130 | static inline int fat_mode_can_hold_ro(struct inode *inode) | ||
| 131 | { | ||
| 132 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | ||
| 133 | mode_t mask; | ||
| 134 | |||
| 135 | if (S_ISDIR(inode->i_mode)) { | ||
| 136 | if (!sbi->options.rodir) | ||
| 137 | return 0; | ||
| 138 | mask = ~sbi->options.fs_dmask; | ||
| 139 | } else | ||
| 140 | mask = ~sbi->options.fs_fmask; | ||
| 141 | |||
| 142 | if (!(mask & S_IWUGO)) | ||
| 143 | return 0; | ||
| 144 | return 1; | ||
| 145 | } | ||
| 146 | |||
| 147 | /* Convert attribute bits and a mask to the UNIX mode. */ | ||
| 148 | static inline mode_t fat_make_mode(struct msdos_sb_info *sbi, | ||
| 149 | u8 attrs, mode_t mode) | ||
| 150 | { | ||
| 151 | if (attrs & ATTR_RO && !((attrs & ATTR_DIR) && !sbi->options.rodir)) | ||
| 152 | mode &= ~S_IWUGO; | ||
| 153 | |||
| 154 | if (attrs & ATTR_DIR) | ||
| 155 | return (mode & ~sbi->options.fs_dmask) | S_IFDIR; | ||
| 156 | else | ||
| 157 | return (mode & ~sbi->options.fs_fmask) | S_IFREG; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* Return the FAT attribute byte for this inode */ | ||
| 161 | static inline u8 fat_make_attrs(struct inode *inode) | ||
| 162 | { | ||
| 163 | u8 attrs = MSDOS_I(inode)->i_attrs; | ||
| 164 | if (S_ISDIR(inode->i_mode)) | ||
| 165 | attrs |= ATTR_DIR; | ||
| 166 | if (fat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO)) | ||
| 167 | attrs |= ATTR_RO; | ||
| 168 | return attrs; | ||
| 169 | } | ||
| 170 | |||
| 171 | static inline void fat_save_attrs(struct inode *inode, u8 attrs) | ||
| 172 | { | ||
| 173 | if (fat_mode_can_hold_ro(inode)) | ||
| 174 | MSDOS_I(inode)->i_attrs = attrs & ATTR_UNUSED; | ||
| 175 | else | ||
| 176 | MSDOS_I(inode)->i_attrs = attrs & (ATTR_UNUSED | ATTR_RO); | ||
| 177 | } | ||
| 178 | |||
| 179 | static inline unsigned char fat_checksum(const __u8 *name) | ||
| 180 | { | ||
| 181 | unsigned char s = name[0]; | ||
| 182 | s = (s<<7) + (s>>1) + name[1]; s = (s<<7) + (s>>1) + name[2]; | ||
| 183 | s = (s<<7) + (s>>1) + name[3]; s = (s<<7) + (s>>1) + name[4]; | ||
| 184 | s = (s<<7) + (s>>1) + name[5]; s = (s<<7) + (s>>1) + name[6]; | ||
| 185 | s = (s<<7) + (s>>1) + name[7]; s = (s<<7) + (s>>1) + name[8]; | ||
| 186 | s = (s<<7) + (s>>1) + name[9]; s = (s<<7) + (s>>1) + name[10]; | ||
| 187 | return s; | ||
| 188 | } | ||
| 189 | |||
| 190 | static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus) | ||
| 191 | { | ||
| 192 | return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus | ||
| 193 | + sbi->data_start; | ||
| 194 | } | ||
| 195 | |||
| 196 | static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len) | ||
| 197 | { | ||
| 198 | #ifdef __BIG_ENDIAN | ||
| 199 | while (len--) { | ||
| 200 | *dst++ = src[0] | (src[1] << 8); | ||
| 201 | src += 2; | ||
| 202 | } | ||
| 203 | #else | ||
| 204 | memcpy(dst, src, len * 2); | ||
| 205 | #endif | ||
| 206 | } | ||
| 207 | |||
| 208 | static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len) | ||
| 209 | { | ||
| 210 | #ifdef __BIG_ENDIAN | ||
| 211 | while (len--) { | ||
| 212 | dst[0] = *src & 0x00FF; | ||
| 213 | dst[1] = (*src & 0xFF00) >> 8; | ||
| 214 | dst += 2; | ||
| 215 | src++; | ||
| 216 | } | ||
| 217 | #else | ||
| 218 | memcpy(dst, src, len * 2); | ||
| 219 | #endif | ||
| 220 | } | ||
| 221 | |||
| 222 | /* fat/cache.c */ | ||
| 223 | extern void fat_cache_inval_inode(struct inode *inode); | ||
| 224 | extern int fat_get_cluster(struct inode *inode, int cluster, | ||
| 225 | int *fclus, int *dclus); | ||
| 226 | extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, | ||
| 227 | unsigned long *mapped_blocks, int create); | ||
| 228 | |||
| 229 | /* fat/dir.c */ | ||
| 230 | extern const struct file_operations fat_dir_operations; | ||
| 231 | extern int fat_search_long(struct inode *inode, const unsigned char *name, | ||
| 232 | int name_len, struct fat_slot_info *sinfo); | ||
| 233 | extern int fat_dir_empty(struct inode *dir); | ||
| 234 | extern int fat_subdirs(struct inode *dir); | ||
| 235 | extern int fat_scan(struct inode *dir, const unsigned char *name, | ||
| 236 | struct fat_slot_info *sinfo); | ||
| 237 | extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, | ||
| 238 | struct msdos_dir_entry **de, loff_t *i_pos); | ||
| 239 | extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); | ||
| 240 | extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots, | ||
| 241 | struct fat_slot_info *sinfo); | ||
| 242 | extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo); | ||
| 243 | |||
| 244 | /* fat/fatent.c */ | ||
| 245 | struct fat_entry { | ||
| 246 | int entry; | ||
| 247 | union { | ||
| 248 | u8 *ent12_p[2]; | ||
| 249 | __le16 *ent16_p; | ||
| 250 | __le32 *ent32_p; | ||
| 251 | } u; | ||
| 252 | int nr_bhs; | ||
| 253 | struct buffer_head *bhs[2]; | ||
| 254 | }; | ||
| 255 | |||
| 256 | static inline void fatent_init(struct fat_entry *fatent) | ||
| 257 | { | ||
| 258 | fatent->nr_bhs = 0; | ||
| 259 | fatent->entry = 0; | ||
| 260 | fatent->u.ent32_p = NULL; | ||
| 261 | fatent->bhs[0] = fatent->bhs[1] = NULL; | ||
| 262 | } | ||
| 263 | |||
| 264 | static inline void fatent_set_entry(struct fat_entry *fatent, int entry) | ||
| 265 | { | ||
| 266 | fatent->entry = entry; | ||
| 267 | fatent->u.ent32_p = NULL; | ||
| 268 | } | ||
| 269 | |||
| 270 | static inline void fatent_brelse(struct fat_entry *fatent) | ||
| 271 | { | ||
| 272 | int i; | ||
| 273 | fatent->u.ent32_p = NULL; | ||
| 274 | for (i = 0; i < fatent->nr_bhs; i++) | ||
| 275 | brelse(fatent->bhs[i]); | ||
| 276 | fatent->nr_bhs = 0; | ||
| 277 | fatent->bhs[0] = fatent->bhs[1] = NULL; | ||
| 278 | } | ||
| 279 | |||
| 280 | extern void fat_ent_access_init(struct super_block *sb); | ||
| 281 | extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent, | ||
| 282 | int entry); | ||
| 283 | extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent, | ||
| 284 | int new, int wait); | ||
| 285 | extern int fat_alloc_clusters(struct inode *inode, int *cluster, | ||
| 286 | int nr_cluster); | ||
| 287 | extern int fat_free_clusters(struct inode *inode, int cluster); | ||
| 288 | extern int fat_count_free_clusters(struct super_block *sb); | ||
| 289 | |||
| 290 | /* fat/file.c */ | ||
| 291 | extern int fat_generic_ioctl(struct inode *inode, struct file *filp, | ||
| 292 | unsigned int cmd, unsigned long arg); | ||
| 293 | extern const struct file_operations fat_file_operations; | ||
| 294 | extern const struct inode_operations fat_file_inode_operations; | ||
| 295 | extern int fat_setattr(struct dentry * dentry, struct iattr * attr); | ||
| 296 | extern void fat_truncate(struct inode *inode); | ||
| 297 | extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, | ||
| 298 | struct kstat *stat); | ||
| 299 | |||
| 300 | /* fat/inode.c */ | ||
| 301 | extern void fat_attach(struct inode *inode, loff_t i_pos); | ||
| 302 | extern void fat_detach(struct inode *inode); | ||
| 303 | extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); | ||
| 304 | extern struct inode *fat_build_inode(struct super_block *sb, | ||
| 305 | struct msdos_dir_entry *de, loff_t i_pos); | ||
| 306 | extern int fat_sync_inode(struct inode *inode); | ||
| 307 | extern int fat_fill_super(struct super_block *sb, void *data, int silent, | ||
| 308 | const struct inode_operations *fs_dir_inode_ops, int isvfat); | ||
| 309 | |||
| 310 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, | ||
| 311 | struct inode *i2); | ||
| 312 | /* fat/misc.c */ | ||
| 313 | extern void fat_fs_panic(struct super_block *s, const char *fmt, ...) | ||
| 314 | __attribute__ ((format (printf, 2, 3))) __cold; | ||
| 315 | extern void fat_clusters_flush(struct super_block *sb); | ||
| 316 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); | ||
| 317 | extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, | ||
| 318 | __le16 __time, __le16 __date, u8 time_cs); | ||
| 319 | extern void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts, | ||
| 320 | __le16 *time, __le16 *date, u8 *time_cs); | ||
| 321 | extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs); | ||
| 322 | |||
| 323 | int fat_cache_init(void); | ||
| 324 | void fat_cache_destroy(void); | ||
| 325 | |||
| 326 | /* helper for printk */ | ||
| 327 | typedef unsigned long long llu; | ||
| 328 | |||
| 329 | #endif /* !_FAT_H */ | ||
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index fb98b3d847ed..da6eea47872f 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/fs.h> | 7 | #include <linux/fs.h> |
| 8 | #include <linux/msdos_fs.h> | 8 | #include <linux/msdos_fs.h> |
| 9 | #include <linux/blkdev.h> | 9 | #include <linux/blkdev.h> |
| 10 | #include "fat.h" | ||
| 10 | 11 | ||
| 11 | struct fatent_operations { | 12 | struct fatent_operations { |
| 12 | void (*ent_blocknr)(struct super_block *, int, int *, sector_t *); | 13 | void (*ent_blocknr)(struct super_block *, int, int *, sector_t *); |
| @@ -92,8 +93,7 @@ static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent, | |||
| 92 | err_brelse: | 93 | err_brelse: |
| 93 | brelse(bhs[0]); | 94 | brelse(bhs[0]); |
| 94 | err: | 95 | err: |
| 95 | printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", | 96 | printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", (llu)blocknr); |
| 96 | (unsigned long long)blocknr); | ||
| 97 | return -EIO; | 97 | return -EIO; |
| 98 | } | 98 | } |
| 99 | 99 | ||
| @@ -106,7 +106,7 @@ static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent, | |||
| 106 | fatent->bhs[0] = sb_bread(sb, blocknr); | 106 | fatent->bhs[0] = sb_bread(sb, blocknr); |
| 107 | if (!fatent->bhs[0]) { | 107 | if (!fatent->bhs[0]) { |
| 108 | printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", | 108 | printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", |
| 109 | (unsigned long long)blocknr); | 109 | (llu)blocknr); |
| 110 | return -EIO; | 110 | return -EIO; |
| 111 | } | 111 | } |
| 112 | fatent->nr_bhs = 1; | 112 | fatent->nr_bhs = 1; |
| @@ -316,10 +316,20 @@ static inline int fat_ent_update_ptr(struct super_block *sb, | |||
| 316 | /* Is this fatent's blocks including this entry? */ | 316 | /* Is this fatent's blocks including this entry? */ |
| 317 | if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr) | 317 | if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr) |
| 318 | return 0; | 318 | return 0; |
| 319 | /* Does this entry need the next block? */ | 319 | if (sbi->fat_bits == 12) { |
| 320 | if (sbi->fat_bits == 12 && (offset + 1) >= sb->s_blocksize) { | 320 | if ((offset + 1) < sb->s_blocksize) { |
| 321 | if (fatent->nr_bhs != 2 || bhs[1]->b_blocknr != (blocknr + 1)) | 321 | /* This entry is on bhs[0]. */ |
| 322 | return 0; | 322 | if (fatent->nr_bhs == 2) { |
| 323 | brelse(bhs[1]); | ||
| 324 | fatent->nr_bhs = 1; | ||
| 325 | } | ||
| 326 | } else { | ||
| 327 | /* This entry needs the next block. */ | ||
| 328 | if (fatent->nr_bhs != 2) | ||
| 329 | return 0; | ||
| 330 | if (bhs[1]->b_blocknr != (blocknr + 1)) | ||
| 331 | return 0; | ||
| 332 | } | ||
| 323 | } | 333 | } |
| 324 | ops->ent_set_ptr(fatent, offset); | 334 | ops->ent_set_ptr(fatent, offset); |
| 325 | return 1; | 335 | return 1; |
diff --git a/fs/fat/file.c b/fs/fat/file.c index ddde37025ca6..f06a4e525ece 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
| @@ -10,13 +10,13 @@ | |||
| 10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
| 11 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
| 12 | #include <linux/time.h> | 12 | #include <linux/time.h> |
| 13 | #include <linux/msdos_fs.h> | ||
| 14 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
| 15 | #include <linux/writeback.h> | 14 | #include <linux/writeback.h> |
| 16 | #include <linux/backing-dev.h> | 15 | #include <linux/backing-dev.h> |
| 17 | #include <linux/blkdev.h> | 16 | #include <linux/blkdev.h> |
| 18 | #include <linux/fsnotify.h> | 17 | #include <linux/fsnotify.h> |
| 19 | #include <linux/security.h> | 18 | #include <linux/security.h> |
| 19 | #include "fat.h" | ||
| 20 | 20 | ||
| 21 | int fat_generic_ioctl(struct inode *inode, struct file *filp, | 21 | int fat_generic_ioctl(struct inode *inode, struct file *filp, |
| 22 | unsigned int cmd, unsigned long arg) | 22 | unsigned int cmd, unsigned long arg) |
| @@ -29,10 +29,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
| 29 | { | 29 | { |
| 30 | u32 attr; | 30 | u32 attr; |
| 31 | 31 | ||
| 32 | if (inode->i_ino == MSDOS_ROOT_INO) | 32 | mutex_lock(&inode->i_mutex); |
| 33 | attr = ATTR_DIR; | 33 | attr = fat_make_attrs(inode); |
| 34 | else | 34 | mutex_unlock(&inode->i_mutex); |
| 35 | attr = fat_attr(inode); | ||
| 36 | 35 | ||
| 37 | return put_user(attr, user_attr); | 36 | return put_user(attr, user_attr); |
| 38 | } | 37 | } |
| @@ -62,20 +61,16 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
| 62 | /* Merge in ATTR_VOLUME and ATTR_DIR */ | 61 | /* Merge in ATTR_VOLUME and ATTR_DIR */ |
| 63 | attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) | | 62 | attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) | |
| 64 | (is_dir ? ATTR_DIR : 0); | 63 | (is_dir ? ATTR_DIR : 0); |
| 65 | oldattr = fat_attr(inode); | 64 | oldattr = fat_make_attrs(inode); |
| 66 | 65 | ||
| 67 | /* Equivalent to a chmod() */ | 66 | /* Equivalent to a chmod() */ |
| 68 | ia.ia_valid = ATTR_MODE | ATTR_CTIME; | 67 | ia.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 69 | ia.ia_ctime = current_fs_time(inode->i_sb); | 68 | ia.ia_ctime = current_fs_time(inode->i_sb); |
| 70 | if (is_dir) { | 69 | if (is_dir) |
| 71 | ia.ia_mode = MSDOS_MKMODE(attr, | 70 | ia.ia_mode = fat_make_mode(sbi, attr, S_IRWXUGO); |
| 72 | S_IRWXUGO & ~sbi->options.fs_dmask) | 71 | else { |
| 73 | | S_IFDIR; | 72 | ia.ia_mode = fat_make_mode(sbi, attr, |
| 74 | } else { | 73 | S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO)); |
| 75 | ia.ia_mode = MSDOS_MKMODE(attr, | ||
| 76 | (S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO)) | ||
| 77 | & ~sbi->options.fs_fmask) | ||
| 78 | | S_IFREG; | ||
| 79 | } | 74 | } |
| 80 | 75 | ||
| 81 | /* The root directory has no attributes */ | 76 | /* The root directory has no attributes */ |
| @@ -115,7 +110,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
| 115 | inode->i_flags &= S_IMMUTABLE; | 110 | inode->i_flags &= S_IMMUTABLE; |
| 116 | } | 111 | } |
| 117 | 112 | ||
| 118 | MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED; | 113 | fat_save_attrs(inode, attr); |
| 119 | mark_inode_dirty(inode); | 114 | mark_inode_dirty(inode); |
| 120 | up: | 115 | up: |
| 121 | mnt_drop_write(filp->f_path.mnt); | 116 | mnt_drop_write(filp->f_path.mnt); |
| @@ -274,7 +269,7 @@ static int fat_sanitize_mode(const struct msdos_sb_info *sbi, | |||
| 274 | 269 | ||
| 275 | /* | 270 | /* |
| 276 | * Note, the basic check is already done by a caller of | 271 | * Note, the basic check is already done by a caller of |
| 277 | * (attr->ia_mode & ~MSDOS_VALID_MODE) | 272 | * (attr->ia_mode & ~FAT_VALID_MODE) |
| 278 | */ | 273 | */ |
| 279 | 274 | ||
| 280 | if (S_ISREG(inode->i_mode)) | 275 | if (S_ISREG(inode->i_mode)) |
| @@ -287,11 +282,18 @@ static int fat_sanitize_mode(const struct msdos_sb_info *sbi, | |||
| 287 | /* | 282 | /* |
| 288 | * Of the r and x bits, all (subject to umask) must be present. Of the | 283 | * Of the r and x bits, all (subject to umask) must be present. Of the |
| 289 | * w bits, either all (subject to umask) or none must be present. | 284 | * w bits, either all (subject to umask) or none must be present. |
| 285 | * | ||
| 286 | * If fat_mode_can_hold_ro(inode) is false, can't change w bits. | ||
| 290 | */ | 287 | */ |
| 291 | if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) | 288 | if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) |
| 292 | return -EPERM; | 289 | return -EPERM; |
| 293 | if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) | 290 | if (fat_mode_can_hold_ro(inode)) { |
| 294 | return -EPERM; | 291 | if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) |
| 292 | return -EPERM; | ||
| 293 | } else { | ||
| 294 | if ((perm & S_IWUGO) != (S_IWUGO & ~mask)) | ||
| 295 | return -EPERM; | ||
| 296 | } | ||
| 295 | 297 | ||
| 296 | *mode_ptr &= S_IFMT | perm; | 298 | *mode_ptr &= S_IFMT | perm; |
| 297 | 299 | ||
| @@ -314,13 +316,15 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode) | |||
| 314 | } | 316 | } |
| 315 | 317 | ||
| 316 | #define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) | 318 | #define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) |
| 319 | /* valid file mode bits */ | ||
| 320 | #define FAT_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXUGO) | ||
| 317 | 321 | ||
| 318 | int fat_setattr(struct dentry *dentry, struct iattr *attr) | 322 | int fat_setattr(struct dentry *dentry, struct iattr *attr) |
| 319 | { | 323 | { |
| 320 | struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); | 324 | struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); |
| 321 | struct inode *inode = dentry->d_inode; | 325 | struct inode *inode = dentry->d_inode; |
| 322 | int error = 0; | ||
| 323 | unsigned int ia_valid; | 326 | unsigned int ia_valid; |
| 327 | int error; | ||
| 324 | 328 | ||
| 325 | /* | 329 | /* |
| 326 | * Expand the file. Since inode_setattr() updates ->i_size | 330 | * Expand the file. Since inode_setattr() updates ->i_size |
| @@ -356,7 +360,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 356 | ((attr->ia_valid & ATTR_GID) && | 360 | ((attr->ia_valid & ATTR_GID) && |
| 357 | (attr->ia_gid != sbi->options.fs_gid)) || | 361 | (attr->ia_gid != sbi->options.fs_gid)) || |
| 358 | ((attr->ia_valid & ATTR_MODE) && | 362 | ((attr->ia_valid & ATTR_MODE) && |
| 359 | (attr->ia_mode & ~MSDOS_VALID_MODE))) | 363 | (attr->ia_mode & ~FAT_VALID_MODE))) |
| 360 | error = -EPERM; | 364 | error = -EPERM; |
| 361 | 365 | ||
| 362 | if (error) { | 366 | if (error) { |
| @@ -374,7 +378,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 374 | attr->ia_valid &= ~ATTR_MODE; | 378 | attr->ia_valid &= ~ATTR_MODE; |
| 375 | } | 379 | } |
| 376 | 380 | ||
| 377 | error = inode_setattr(inode, attr); | 381 | if (attr->ia_valid) |
| 382 | error = inode_setattr(inode, attr); | ||
| 378 | out: | 383 | out: |
| 379 | return error; | 384 | return error; |
| 380 | } | 385 | } |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 19eafbe3c379..bdd8fb7be2ca 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
| 17 | #include <linux/smp_lock.h> | 17 | #include <linux/smp_lock.h> |
| 18 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
| 19 | #include <linux/msdos_fs.h> | ||
| 20 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
| 21 | #include <linux/mpage.h> | 20 | #include <linux/mpage.h> |
| 22 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
| @@ -27,7 +26,9 @@ | |||
| 27 | #include <linux/uio.h> | 26 | #include <linux/uio.h> |
| 28 | #include <linux/writeback.h> | 27 | #include <linux/writeback.h> |
| 29 | #include <linux/log2.h> | 28 | #include <linux/log2.h> |
| 29 | #include <linux/hash.h> | ||
| 30 | #include <asm/unaligned.h> | 30 | #include <asm/unaligned.h> |
| 31 | #include "fat.h" | ||
| 31 | 32 | ||
| 32 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET | 33 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET |
| 33 | /* if user don't select VFAT, this is undefined. */ | 34 | /* if user don't select VFAT, this is undefined. */ |
| @@ -63,7 +64,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock, | |||
| 63 | sector_t phys; | 64 | sector_t phys; |
| 64 | int err, offset; | 65 | int err, offset; |
| 65 | 66 | ||
| 66 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 67 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create); |
| 67 | if (err) | 68 | if (err) |
| 68 | return err; | 69 | return err; |
| 69 | if (phys) { | 70 | if (phys) { |
| @@ -93,7 +94,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock, | |||
| 93 | *max_blocks = min(mapped_blocks, *max_blocks); | 94 | *max_blocks = min(mapped_blocks, *max_blocks); |
| 94 | MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits; | 95 | MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits; |
| 95 | 96 | ||
| 96 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 97 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create); |
| 97 | if (err) | 98 | if (err) |
| 98 | return err; | 99 | return err; |
| 99 | 100 | ||
| @@ -175,7 +176,7 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
| 175 | 176 | ||
| 176 | if (rw == WRITE) { | 177 | if (rw == WRITE) { |
| 177 | /* | 178 | /* |
| 178 | * FIXME: blockdev_direct_IO() doesn't use ->prepare_write(), | 179 | * FIXME: blockdev_direct_IO() doesn't use ->write_begin(), |
| 179 | * so we need to update the ->mmu_private to block boundary. | 180 | * so we need to update the ->mmu_private to block boundary. |
| 180 | * | 181 | * |
| 181 | * But we must fill the remaining area or hole by nul for | 182 | * But we must fill the remaining area or hole by nul for |
| @@ -198,7 +199,14 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
| 198 | 199 | ||
| 199 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) | 200 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) |
| 200 | { | 201 | { |
| 201 | return generic_block_bmap(mapping, block, fat_get_block); | 202 | sector_t blocknr; |
| 203 | |||
| 204 | /* fat_get_cluster() assumes the requested blocknr isn't truncated. */ | ||
| 205 | mutex_lock(&mapping->host->i_mutex); | ||
| 206 | blocknr = generic_block_bmap(mapping, block, fat_get_block); | ||
| 207 | mutex_unlock(&mapping->host->i_mutex); | ||
| 208 | |||
| 209 | return blocknr; | ||
| 202 | } | 210 | } |
| 203 | 211 | ||
| 204 | static const struct address_space_operations fat_aops = { | 212 | static const struct address_space_operations fat_aops = { |
| @@ -247,25 +255,21 @@ static void fat_hash_init(struct super_block *sb) | |||
| 247 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); | 255 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); |
| 248 | } | 256 | } |
| 249 | 257 | ||
| 250 | static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) | 258 | static inline unsigned long fat_hash(loff_t i_pos) |
| 251 | { | 259 | { |
| 252 | unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb; | 260 | return hash_32(i_pos, FAT_HASH_BITS); |
| 253 | tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2); | ||
| 254 | return tmp & FAT_HASH_MASK; | ||
| 255 | } | 261 | } |
| 256 | 262 | ||
| 257 | void fat_attach(struct inode *inode, loff_t i_pos) | 263 | void fat_attach(struct inode *inode, loff_t i_pos) |
| 258 | { | 264 | { |
| 259 | struct super_block *sb = inode->i_sb; | 265 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
| 260 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 266 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); |
| 261 | 267 | ||
| 262 | spin_lock(&sbi->inode_hash_lock); | 268 | spin_lock(&sbi->inode_hash_lock); |
| 263 | MSDOS_I(inode)->i_pos = i_pos; | 269 | MSDOS_I(inode)->i_pos = i_pos; |
| 264 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, | 270 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, head); |
| 265 | sbi->inode_hashtable + fat_hash(sb, i_pos)); | ||
| 266 | spin_unlock(&sbi->inode_hash_lock); | 271 | spin_unlock(&sbi->inode_hash_lock); |
| 267 | } | 272 | } |
| 268 | |||
| 269 | EXPORT_SYMBOL_GPL(fat_attach); | 273 | EXPORT_SYMBOL_GPL(fat_attach); |
| 270 | 274 | ||
| 271 | void fat_detach(struct inode *inode) | 275 | void fat_detach(struct inode *inode) |
| @@ -276,13 +280,12 @@ void fat_detach(struct inode *inode) | |||
| 276 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); | 280 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); |
| 277 | spin_unlock(&sbi->inode_hash_lock); | 281 | spin_unlock(&sbi->inode_hash_lock); |
| 278 | } | 282 | } |
| 279 | |||
| 280 | EXPORT_SYMBOL_GPL(fat_detach); | 283 | EXPORT_SYMBOL_GPL(fat_detach); |
| 281 | 284 | ||
| 282 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) | 285 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) |
| 283 | { | 286 | { |
| 284 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 287 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
| 285 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos); | 288 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); |
| 286 | struct hlist_node *_p; | 289 | struct hlist_node *_p; |
| 287 | struct msdos_inode_info *i; | 290 | struct msdos_inode_info *i; |
| 288 | struct inode *inode = NULL; | 291 | struct inode *inode = NULL; |
| @@ -341,8 +344,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
| 341 | 344 | ||
| 342 | if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { | 345 | if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { |
| 343 | inode->i_generation &= ~1; | 346 | inode->i_generation &= ~1; |
| 344 | inode->i_mode = MSDOS_MKMODE(de->attr, | 347 | inode->i_mode = fat_make_mode(sbi, de->attr, S_IRWXUGO); |
| 345 | S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; | ||
| 346 | inode->i_op = sbi->dir_ops; | 348 | inode->i_op = sbi->dir_ops; |
| 347 | inode->i_fop = &fat_dir_operations; | 349 | inode->i_fop = &fat_dir_operations; |
| 348 | 350 | ||
| @@ -359,10 +361,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
| 359 | inode->i_nlink = fat_subdirs(inode); | 361 | inode->i_nlink = fat_subdirs(inode); |
| 360 | } else { /* not a directory */ | 362 | } else { /* not a directory */ |
| 361 | inode->i_generation |= 1; | 363 | inode->i_generation |= 1; |
| 362 | inode->i_mode = MSDOS_MKMODE(de->attr, | 364 | inode->i_mode = fat_make_mode(sbi, de->attr, |
| 363 | ((sbi->options.showexec && !is_exec(de->name + 8)) | 365 | ((sbi->options.showexec && !is_exec(de->name + 8)) |
| 364 | ? S_IRUGO|S_IWUGO : S_IRWXUGO) | 366 | ? S_IRUGO|S_IWUGO : S_IRWXUGO)); |
| 365 | & ~sbi->options.fs_fmask) | S_IFREG; | ||
| 366 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); | 367 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); |
| 367 | if (sbi->fat_bits == 32) | 368 | if (sbi->fat_bits == 32) |
| 368 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); | 369 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); |
| @@ -378,25 +379,16 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
| 378 | if (sbi->options.sys_immutable) | 379 | if (sbi->options.sys_immutable) |
| 379 | inode->i_flags |= S_IMMUTABLE; | 380 | inode->i_flags |= S_IMMUTABLE; |
| 380 | } | 381 | } |
| 381 | MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; | 382 | fat_save_attrs(inode, de->attr); |
| 383 | |||
| 382 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) | 384 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) |
| 383 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; | 385 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; |
| 384 | inode->i_mtime.tv_sec = | 386 | |
| 385 | date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date), | 387 | fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0); |
| 386 | sbi->options.tz_utc); | ||
| 387 | inode->i_mtime.tv_nsec = 0; | ||
| 388 | if (sbi->options.isvfat) { | 388 | if (sbi->options.isvfat) { |
| 389 | int secs = de->ctime_cs / 100; | 389 | fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime, |
| 390 | int csecs = de->ctime_cs % 100; | 390 | de->cdate, de->ctime_cs); |
| 391 | inode->i_ctime.tv_sec = | 391 | fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0); |
| 392 | date_dos2unix(le16_to_cpu(de->ctime), | ||
| 393 | le16_to_cpu(de->cdate), | ||
| 394 | sbi->options.tz_utc) + secs; | ||
| 395 | inode->i_ctime.tv_nsec = csecs * 10000000; | ||
| 396 | inode->i_atime.tv_sec = | ||
| 397 | date_dos2unix(0, le16_to_cpu(de->adate), | ||
| 398 | sbi->options.tz_utc); | ||
| 399 | inode->i_atime.tv_nsec = 0; | ||
| 400 | } else | 392 | } else |
| 401 | inode->i_ctime = inode->i_atime = inode->i_mtime; | 393 | inode->i_ctime = inode->i_atime = inode->i_mtime; |
| 402 | 394 | ||
| @@ -443,13 +435,8 @@ static void fat_delete_inode(struct inode *inode) | |||
| 443 | 435 | ||
| 444 | static void fat_clear_inode(struct inode *inode) | 436 | static void fat_clear_inode(struct inode *inode) |
| 445 | { | 437 | { |
| 446 | struct super_block *sb = inode->i_sb; | ||
| 447 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | ||
| 448 | |||
| 449 | spin_lock(&sbi->inode_hash_lock); | ||
| 450 | fat_cache_inval_inode(inode); | 438 | fat_cache_inval_inode(inode); |
| 451 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); | 439 | fat_detach(inode); |
| 452 | spin_unlock(&sbi->inode_hash_lock); | ||
| 453 | } | 440 | } |
| 454 | 441 | ||
| 455 | static void fat_write_super(struct super_block *sb) | 442 | static void fat_write_super(struct super_block *sb) |
| @@ -555,6 +542,20 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 555 | return 0; | 542 | return 0; |
| 556 | } | 543 | } |
| 557 | 544 | ||
| 545 | static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, | ||
| 546 | struct inode *inode) | ||
| 547 | { | ||
| 548 | loff_t i_pos; | ||
| 549 | #if BITS_PER_LONG == 32 | ||
| 550 | spin_lock(&sbi->inode_hash_lock); | ||
| 551 | #endif | ||
| 552 | i_pos = MSDOS_I(inode)->i_pos; | ||
| 553 | #if BITS_PER_LONG == 32 | ||
| 554 | spin_unlock(&sbi->inode_hash_lock); | ||
| 555 | #endif | ||
| 556 | return i_pos; | ||
| 557 | } | ||
| 558 | |||
| 558 | static int fat_write_inode(struct inode *inode, int wait) | 559 | static int fat_write_inode(struct inode *inode, int wait) |
| 559 | { | 560 | { |
| 560 | struct super_block *sb = inode->i_sb; | 561 | struct super_block *sb = inode->i_sb; |
| @@ -564,9 +565,12 @@ static int fat_write_inode(struct inode *inode, int wait) | |||
| 564 | loff_t i_pos; | 565 | loff_t i_pos; |
| 565 | int err; | 566 | int err; |
| 566 | 567 | ||
| 568 | if (inode->i_ino == MSDOS_ROOT_INO) | ||
| 569 | return 0; | ||
| 570 | |||
| 567 | retry: | 571 | retry: |
| 568 | i_pos = MSDOS_I(inode)->i_pos; | 572 | i_pos = fat_i_pos_read(sbi, inode); |
| 569 | if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) | 573 | if (!i_pos) |
| 570 | return 0; | 574 | return 0; |
| 571 | 575 | ||
| 572 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); | 576 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); |
| @@ -588,19 +592,17 @@ retry: | |||
| 588 | raw_entry->size = 0; | 592 | raw_entry->size = 0; |
| 589 | else | 593 | else |
| 590 | raw_entry->size = cpu_to_le32(inode->i_size); | 594 | raw_entry->size = cpu_to_le32(inode->i_size); |
| 591 | raw_entry->attr = fat_attr(inode); | 595 | raw_entry->attr = fat_make_attrs(inode); |
| 592 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); | 596 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); |
| 593 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); | 597 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); |
| 594 | fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, | 598 | fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time, |
| 595 | &raw_entry->date, sbi->options.tz_utc); | 599 | &raw_entry->date, NULL); |
| 596 | if (sbi->options.isvfat) { | 600 | if (sbi->options.isvfat) { |
| 597 | __le16 atime; | 601 | __le16 atime; |
| 598 | fat_date_unix2dos(inode->i_ctime.tv_sec, &raw_entry->ctime, | 602 | fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime, |
| 599 | &raw_entry->cdate, sbi->options.tz_utc); | 603 | &raw_entry->cdate, &raw_entry->ctime_cs); |
| 600 | fat_date_unix2dos(inode->i_atime.tv_sec, &atime, | 604 | fat_time_unix2fat(sbi, &inode->i_atime, &atime, |
| 601 | &raw_entry->adate, sbi->options.tz_utc); | 605 | &raw_entry->adate, NULL); |
| 602 | raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + | ||
| 603 | inode->i_ctime.tv_nsec / 10000000; | ||
| 604 | } | 606 | } |
| 605 | spin_unlock(&sbi->inode_hash_lock); | 607 | spin_unlock(&sbi->inode_hash_lock); |
| 606 | mark_buffer_dirty(bh); | 608 | mark_buffer_dirty(bh); |
| @@ -819,8 +821,10 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
| 819 | seq_puts(m, ",uni_xlate"); | 821 | seq_puts(m, ",uni_xlate"); |
| 820 | if (!opts->numtail) | 822 | if (!opts->numtail) |
| 821 | seq_puts(m, ",nonumtail"); | 823 | seq_puts(m, ",nonumtail"); |
| 824 | if (opts->rodir) | ||
| 825 | seq_puts(m, ",rodir"); | ||
| 822 | } | 826 | } |
| 823 | if (sbi->options.flush) | 827 | if (opts->flush) |
| 824 | seq_puts(m, ",flush"); | 828 | seq_puts(m, ",flush"); |
| 825 | if (opts->tz_utc) | 829 | if (opts->tz_utc) |
| 826 | seq_puts(m, ",tz=UTC"); | 830 | seq_puts(m, ",tz=UTC"); |
| @@ -836,7 +840,7 @@ enum { | |||
| 836 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, | 840 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, |
| 837 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 841 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, |
| 838 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 842 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
| 839 | Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_err, | 843 | Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err, |
| 840 | }; | 844 | }; |
| 841 | 845 | ||
| 842 | static const match_table_t fat_tokens = { | 846 | static const match_table_t fat_tokens = { |
| @@ -908,6 +912,7 @@ static const match_table_t vfat_tokens = { | |||
| 908 | {Opt_nonumtail_yes, "nonumtail=yes"}, | 912 | {Opt_nonumtail_yes, "nonumtail=yes"}, |
| 909 | {Opt_nonumtail_yes, "nonumtail=true"}, | 913 | {Opt_nonumtail_yes, "nonumtail=true"}, |
| 910 | {Opt_nonumtail_yes, "nonumtail"}, | 914 | {Opt_nonumtail_yes, "nonumtail"}, |
| 915 | {Opt_rodir, "rodir"}, | ||
| 911 | {Opt_err, NULL} | 916 | {Opt_err, NULL} |
| 912 | }; | 917 | }; |
| 913 | 918 | ||
| @@ -927,10 +932,13 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
| 927 | opts->allow_utime = -1; | 932 | opts->allow_utime = -1; |
| 928 | opts->codepage = fat_default_codepage; | 933 | opts->codepage = fat_default_codepage; |
| 929 | opts->iocharset = fat_default_iocharset; | 934 | opts->iocharset = fat_default_iocharset; |
| 930 | if (is_vfat) | 935 | if (is_vfat) { |
| 931 | opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; | 936 | opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; |
| 932 | else | 937 | opts->rodir = 0; |
| 938 | } else { | ||
| 933 | opts->shortname = 0; | 939 | opts->shortname = 0; |
| 940 | opts->rodir = 1; | ||
| 941 | } | ||
| 934 | opts->name_check = 'n'; | 942 | opts->name_check = 'n'; |
| 935 | opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; | 943 | opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; |
| 936 | opts->utf8 = opts->unicode_xlate = 0; | 944 | opts->utf8 = opts->unicode_xlate = 0; |
| @@ -1081,6 +1089,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
| 1081 | case Opt_nonumtail_yes: /* empty or 1 or yes or true */ | 1089 | case Opt_nonumtail_yes: /* empty or 1 or yes or true */ |
| 1082 | opts->numtail = 0; /* negated option */ | 1090 | opts->numtail = 0; /* negated option */ |
| 1083 | break; | 1091 | break; |
| 1092 | case Opt_rodir: | ||
| 1093 | opts->rodir = 1; | ||
| 1094 | break; | ||
| 1084 | 1095 | ||
| 1085 | /* obsolete mount options */ | 1096 | /* obsolete mount options */ |
| 1086 | case Opt_obsolate: | 1097 | case Opt_obsolate: |
| @@ -1126,7 +1137,7 @@ static int fat_read_root(struct inode *inode) | |||
| 1126 | inode->i_gid = sbi->options.fs_gid; | 1137 | inode->i_gid = sbi->options.fs_gid; |
| 1127 | inode->i_version++; | 1138 | inode->i_version++; |
| 1128 | inode->i_generation = 0; | 1139 | inode->i_generation = 0; |
| 1129 | inode->i_mode = (S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; | 1140 | inode->i_mode = fat_make_mode(sbi, ATTR_DIR, S_IRWXUGO); |
| 1130 | inode->i_op = sbi->dir_ops; | 1141 | inode->i_op = sbi->dir_ops; |
| 1131 | inode->i_fop = &fat_dir_operations; | 1142 | inode->i_fop = &fat_dir_operations; |
| 1132 | if (sbi->fat_bits == 32) { | 1143 | if (sbi->fat_bits == 32) { |
| @@ -1143,7 +1154,7 @@ static int fat_read_root(struct inode *inode) | |||
| 1143 | MSDOS_I(inode)->i_logstart = 0; | 1154 | MSDOS_I(inode)->i_logstart = 0; |
| 1144 | MSDOS_I(inode)->mmu_private = inode->i_size; | 1155 | MSDOS_I(inode)->mmu_private = inode->i_size; |
| 1145 | 1156 | ||
| 1146 | MSDOS_I(inode)->i_attrs = ATTR_NONE; | 1157 | fat_save_attrs(inode, ATTR_DIR); |
| 1147 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0; | 1158 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0; |
| 1148 | inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0; | 1159 | inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0; |
| 1149 | inode->i_nlink = fat_subdirs(inode)+2; | 1160 | inode->i_nlink = fat_subdirs(inode)+2; |
diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 79fb98ad36d4..ac39ebcc1496 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | 8 | ||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
| 11 | #include <linux/msdos_fs.h> | ||
| 12 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
| 12 | #include "fat.h" | ||
| 13 | 13 | ||
| 14 | /* | 14 | /* |
| 15 | * fat_fs_panic reports a severe file system problem and sets the file system | 15 | * fat_fs_panic reports a severe file system problem and sets the file system |
| @@ -124,8 +124,9 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster) | |||
| 124 | mark_inode_dirty(inode); | 124 | mark_inode_dirty(inode); |
| 125 | } | 125 | } |
| 126 | if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) { | 126 | if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) { |
| 127 | fat_fs_panic(sb, "clusters badly computed (%d != %lu)", | 127 | fat_fs_panic(sb, "clusters badly computed (%d != %llu)", |
| 128 | new_fclus, inode->i_blocks >> (sbi->cluster_bits - 9)); | 128 | new_fclus, |
| 129 | (llu)(inode->i_blocks >> (sbi->cluster_bits - 9))); | ||
| 129 | fat_cache_inval_inode(inode); | 130 | fat_cache_inval_inode(inode); |
| 130 | } | 131 | } |
| 131 | inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9); | 132 | inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9); |
| @@ -135,65 +136,131 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster) | |||
| 135 | 136 | ||
| 136 | extern struct timezone sys_tz; | 137 | extern struct timezone sys_tz; |
| 137 | 138 | ||
| 139 | /* | ||
| 140 | * The epoch of FAT timestamp is 1980. | ||
| 141 | * : bits : value | ||
| 142 | * date: 0 - 4: day (1 - 31) | ||
| 143 | * date: 5 - 8: month (1 - 12) | ||
| 144 | * date: 9 - 15: year (0 - 127) from 1980 | ||
| 145 | * time: 0 - 4: sec (0 - 29) 2sec counts | ||
| 146 | * time: 5 - 10: min (0 - 59) | ||
| 147 | * time: 11 - 15: hour (0 - 23) | ||
| 148 | */ | ||
| 149 | #define SECS_PER_MIN 60 | ||
| 150 | #define SECS_PER_HOUR (60 * 60) | ||
| 151 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) | ||
| 152 | #define UNIX_SECS_1980 315532800L | ||
| 153 | #if BITS_PER_LONG == 64 | ||
| 154 | #define UNIX_SECS_2108 4354819200L | ||
| 155 | #endif | ||
| 156 | /* days between 1.1.70 and 1.1.80 (2 leap days) */ | ||
| 157 | #define DAYS_DELTA (365 * 10 + 2) | ||
| 158 | /* 120 (2100 - 1980) isn't leap year */ | ||
| 159 | #define YEAR_2100 120 | ||
| 160 | #define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != YEAR_2100) | ||
| 161 | |||
| 138 | /* Linear day numbers of the respective 1sts in non-leap years. */ | 162 | /* Linear day numbers of the respective 1sts in non-leap years. */ |
| 139 | static int day_n[] = { | 163 | static time_t days_in_year[] = { |
| 140 | /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ | 164 | /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ |
| 141 | 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0 | 165 | 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, |
| 142 | }; | 166 | }; |
| 143 | 167 | ||
| 144 | /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ | 168 | /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ |
| 145 | int date_dos2unix(unsigned short time, unsigned short date, int tz_utc) | 169 | void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, |
| 170 | __le16 __time, __le16 __date, u8 time_cs) | ||
| 146 | { | 171 | { |
| 147 | int month, year, secs; | 172 | u16 time = le16_to_cpu(__time), date = le16_to_cpu(__date); |
| 173 | time_t second, day, leap_day, month, year; | ||
| 148 | 174 | ||
| 149 | /* | 175 | year = date >> 9; |
| 150 | * first subtract and mask after that... Otherwise, if | 176 | month = max(1, (date >> 5) & 0xf); |
| 151 | * date == 0, bad things happen | 177 | day = max(1, date & 0x1f) - 1; |
| 152 | */ | 178 | |
| 153 | month = ((date >> 5) - 1) & 15; | 179 | leap_day = (year + 3) / 4; |
| 154 | year = date >> 9; | 180 | if (year > YEAR_2100) /* 2100 isn't leap year */ |
| 155 | secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* | 181 | leap_day--; |
| 156 | ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && | 182 | if (IS_LEAP_YEAR(year) && month > 2) |
| 157 | month < 2 ? 1 : 0)+3653); | 183 | leap_day++; |
| 158 | /* days since 1.1.70 plus 80's leap day */ | 184 | |
| 159 | if (!tz_utc) | 185 | second = (time & 0x1f) << 1; |
| 160 | secs += sys_tz.tz_minuteswest*60; | 186 | second += ((time >> 5) & 0x3f) * SECS_PER_MIN; |
| 161 | return secs; | 187 | second += (time >> 11) * SECS_PER_HOUR; |
| 188 | second += (year * 365 + leap_day | ||
| 189 | + days_in_year[month] + day | ||
| 190 | + DAYS_DELTA) * SECS_PER_DAY; | ||
| 191 | |||
| 192 | if (!sbi->options.tz_utc) | ||
| 193 | second += sys_tz.tz_minuteswest * SECS_PER_MIN; | ||
| 194 | |||
| 195 | if (time_cs) { | ||
| 196 | ts->tv_sec = second + (time_cs / 100); | ||
| 197 | ts->tv_nsec = (time_cs % 100) * 10000000; | ||
| 198 | } else { | ||
| 199 | ts->tv_sec = second; | ||
| 200 | ts->tv_nsec = 0; | ||
| 201 | } | ||
| 162 | } | 202 | } |
| 163 | 203 | ||
| 164 | /* Convert linear UNIX date to a MS-DOS time/date pair. */ | 204 | /* Convert linear UNIX date to a FAT time/date pair. */ |
| 165 | void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int tz_utc) | 205 | void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts, |
| 206 | __le16 *time, __le16 *date, u8 *time_cs) | ||
| 166 | { | 207 | { |
| 167 | int day, year, nl_day, month; | 208 | time_t second = ts->tv_sec; |
| 209 | time_t day, leap_day, month, year; | ||
| 168 | 210 | ||
| 169 | if (!tz_utc) | 211 | if (!sbi->options.tz_utc) |
| 170 | unix_date -= sys_tz.tz_minuteswest*60; | 212 | second -= sys_tz.tz_minuteswest * SECS_PER_MIN; |
| 171 | 213 | ||
| 172 | /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ | 214 | /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ |
| 173 | if (unix_date < 315532800) | 215 | if (second < UNIX_SECS_1980) { |
| 174 | unix_date = 315532800; | 216 | *time = 0; |
| 175 | 217 | *date = cpu_to_le16((0 << 9) | (1 << 5) | 1); | |
| 176 | *time = cpu_to_le16((unix_date % 60)/2+(((unix_date/60) % 60) << 5)+ | 218 | if (time_cs) |
| 177 | (((unix_date/3600) % 24) << 11)); | 219 | *time_cs = 0; |
| 178 | day = unix_date/86400-3652; | 220 | return; |
| 179 | year = day/365; | 221 | } |
| 180 | if ((year+3)/4+365*year > day) | 222 | #if BITS_PER_LONG == 64 |
| 223 | if (second >= UNIX_SECS_2108) { | ||
| 224 | *time = cpu_to_le16((23 << 11) | (59 << 5) | 29); | ||
| 225 | *date = cpu_to_le16((127 << 9) | (12 << 5) | 31); | ||
| 226 | if (time_cs) | ||
| 227 | *time_cs = 199; | ||
| 228 | return; | ||
| 229 | } | ||
| 230 | #endif | ||
| 231 | |||
| 232 | day = second / SECS_PER_DAY - DAYS_DELTA; | ||
| 233 | year = day / 365; | ||
| 234 | leap_day = (year + 3) / 4; | ||
| 235 | if (year > YEAR_2100) /* 2100 isn't leap year */ | ||
| 236 | leap_day--; | ||
| 237 | if (year * 365 + leap_day > day) | ||
| 181 | year--; | 238 | year--; |
| 182 | day -= (year+3)/4+365*year; | 239 | leap_day = (year + 3) / 4; |
| 183 | if (day == 59 && !(year & 3)) { | 240 | if (year > YEAR_2100) /* 2100 isn't leap year */ |
| 184 | nl_day = day; | 241 | leap_day--; |
| 242 | day -= year * 365 + leap_day; | ||
| 243 | |||
| 244 | if (IS_LEAP_YEAR(year) && day == days_in_year[3]) { | ||
| 185 | month = 2; | 245 | month = 2; |
| 186 | } else { | 246 | } else { |
| 187 | nl_day = (year & 3) || day <= 59 ? day : day-1; | 247 | if (IS_LEAP_YEAR(year) && day > days_in_year[3]) |
| 188 | for (month = 0; month < 12; month++) { | 248 | day--; |
| 189 | if (day_n[month] > nl_day) | 249 | for (month = 1; month < 12; month++) { |
| 250 | if (days_in_year[month + 1] > day) | ||
| 190 | break; | 251 | break; |
| 191 | } | 252 | } |
| 192 | } | 253 | } |
| 193 | *date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9)); | 254 | day -= days_in_year[month]; |
| 194 | } | ||
| 195 | 255 | ||
| 196 | EXPORT_SYMBOL_GPL(fat_date_unix2dos); | 256 | *time = cpu_to_le16(((second / SECS_PER_HOUR) % 24) << 11 |
| 257 | | ((second / SECS_PER_MIN) % 60) << 5 | ||
| 258 | | (second % SECS_PER_MIN) >> 1); | ||
| 259 | *date = cpu_to_le16((year << 9) | (month << 5) | (day + 1)); | ||
| 260 | if (time_cs) | ||
| 261 | *time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000; | ||
| 262 | } | ||
| 263 | EXPORT_SYMBOL_GPL(fat_time_unix2fat); | ||
| 197 | 264 | ||
| 198 | int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) | 265 | int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) |
| 199 | { | 266 | { |
diff --git a/fs/msdos/namei.c b/fs/fat/namei_msdos.c index e844b9809d27..7ba03a4acbe0 100644 --- a/fs/msdos/namei.c +++ b/fs/fat/namei_msdos.c | |||
| @@ -9,8 +9,8 @@ | |||
| 9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
| 10 | #include <linux/time.h> | 10 | #include <linux/time.h> |
| 11 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
| 12 | #include <linux/msdos_fs.h> | ||
| 13 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
| 13 | #include "fat.h" | ||
| 14 | 14 | ||
| 15 | /* Characters that are undesirable in an MS-DOS file name */ | 15 | /* Characters that are undesirable in an MS-DOS file name */ |
| 16 | static unsigned char bad_chars[] = "*?<>|\""; | 16 | static unsigned char bad_chars[] = "*?<>|\""; |
| @@ -203,33 +203,37 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, | |||
| 203 | { | 203 | { |
| 204 | struct super_block *sb = dir->i_sb; | 204 | struct super_block *sb = dir->i_sb; |
| 205 | struct fat_slot_info sinfo; | 205 | struct fat_slot_info sinfo; |
| 206 | struct inode *inode = NULL; | 206 | struct inode *inode; |
| 207 | int res; | 207 | int err; |
| 208 | |||
| 209 | dentry->d_op = &msdos_dentry_operations; | ||
| 210 | 208 | ||
| 211 | lock_super(sb); | 209 | lock_super(sb); |
| 212 | res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); | 210 | |
| 213 | if (res == -ENOENT) | 211 | err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); |
| 214 | goto add; | 212 | if (err) { |
| 215 | if (res < 0) | 213 | if (err == -ENOENT) { |
| 216 | goto out; | 214 | inode = NULL; |
| 215 | goto out; | ||
| 216 | } | ||
| 217 | goto error; | ||
| 218 | } | ||
| 219 | |||
| 217 | inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); | 220 | inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); |
| 218 | brelse(sinfo.bh); | 221 | brelse(sinfo.bh); |
| 219 | if (IS_ERR(inode)) { | 222 | if (IS_ERR(inode)) { |
| 220 | res = PTR_ERR(inode); | 223 | err = PTR_ERR(inode); |
| 221 | goto out; | 224 | goto error; |
| 222 | } | 225 | } |
| 223 | add: | 226 | out: |
| 224 | res = 0; | 227 | unlock_super(sb); |
| 228 | dentry->d_op = &msdos_dentry_operations; | ||
| 225 | dentry = d_splice_alias(inode, dentry); | 229 | dentry = d_splice_alias(inode, dentry); |
| 226 | if (dentry) | 230 | if (dentry) |
| 227 | dentry->d_op = &msdos_dentry_operations; | 231 | dentry->d_op = &msdos_dentry_operations; |
| 228 | out: | 232 | return dentry; |
| 233 | |||
| 234 | error: | ||
| 229 | unlock_super(sb); | 235 | unlock_super(sb); |
| 230 | if (!res) | 236 | return ERR_PTR(err); |
| 231 | return dentry; | ||
| 232 | return ERR_PTR(res); | ||
| 233 | } | 237 | } |
| 234 | 238 | ||
| 235 | /***** Creates a directory entry (name is already formatted). */ | 239 | /***** Creates a directory entry (name is already formatted). */ |
| @@ -247,7 +251,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, | |||
| 247 | if (is_hid) | 251 | if (is_hid) |
| 248 | de.attr |= ATTR_HIDDEN; | 252 | de.attr |= ATTR_HIDDEN; |
| 249 | de.lcase = 0; | 253 | de.lcase = 0; |
| 250 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); | 254 | fat_time_unix2fat(sbi, ts, &time, &date, NULL); |
| 251 | de.cdate = de.adate = 0; | 255 | de.cdate = de.adate = 0; |
| 252 | de.ctime = 0; | 256 | de.ctime = 0; |
| 253 | de.ctime_cs = 0; | 257 | de.ctime_cs = 0; |
diff --git a/fs/vfat/namei.c b/fs/fat/namei_vfat.c index 155c10b4adbd..bf326d4356a3 100644 --- a/fs/vfat/namei.c +++ b/fs/fat/namei_vfat.c | |||
| @@ -16,36 +16,75 @@ | |||
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | |||
| 20 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
| 21 | #include <linux/msdos_fs.h> | ||
| 22 | #include <linux/ctype.h> | 20 | #include <linux/ctype.h> |
| 23 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 24 | #include <linux/smp_lock.h> | 22 | #include <linux/smp_lock.h> |
| 25 | #include <linux/buffer_head.h> | 23 | #include <linux/buffer_head.h> |
| 26 | #include <linux/namei.h> | 24 | #include <linux/namei.h> |
| 25 | #include "fat.h" | ||
| 27 | 26 | ||
| 28 | static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) | 27 | /* |
| 28 | * If new entry was created in the parent, it could create the 8.3 | ||
| 29 | * alias (the shortname of logname). So, the parent may have the | ||
| 30 | * negative-dentry which matches the created 8.3 alias. | ||
| 31 | * | ||
| 32 | * If it happened, the negative dentry isn't actually negative | ||
| 33 | * anymore. So, drop it. | ||
| 34 | */ | ||
| 35 | static int vfat_revalidate_shortname(struct dentry *dentry) | ||
| 29 | { | 36 | { |
| 30 | int ret = 1; | 37 | int ret = 1; |
| 31 | 38 | spin_lock(&dentry->d_lock); | |
| 32 | if (!dentry->d_inode && | 39 | if (dentry->d_time != dentry->d_parent->d_inode->i_version) |
| 33 | nd && !(nd->flags & LOOKUP_CONTINUE) && (nd->flags & LOOKUP_CREATE)) | ||
| 34 | /* | ||
| 35 | * negative dentry is dropped, in order to make sure | ||
| 36 | * to use the name which a user desires if this is | ||
| 37 | * create path. | ||
| 38 | */ | ||
| 39 | ret = 0; | 40 | ret = 0; |
| 40 | else { | 41 | spin_unlock(&dentry->d_lock); |
| 41 | spin_lock(&dentry->d_lock); | ||
| 42 | if (dentry->d_time != dentry->d_parent->d_inode->i_version) | ||
| 43 | ret = 0; | ||
| 44 | spin_unlock(&dentry->d_lock); | ||
| 45 | } | ||
| 46 | return ret; | 42 | return ret; |
| 47 | } | 43 | } |
| 48 | 44 | ||
| 45 | static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
| 46 | { | ||
| 47 | /* This is not negative dentry. Always valid. */ | ||
| 48 | if (dentry->d_inode) | ||
| 49 | return 1; | ||
| 50 | return vfat_revalidate_shortname(dentry); | ||
| 51 | } | ||
| 52 | |||
| 53 | static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) | ||
| 54 | { | ||
| 55 | /* | ||
| 56 | * This is not negative dentry. Always valid. | ||
| 57 | * | ||
| 58 | * Note, rename() to existing directory entry will have ->d_inode, | ||
| 59 | * and will use existing name which isn't specified name by user. | ||
| 60 | * | ||
| 61 | * We may be able to drop this positive dentry here. But dropping | ||
| 62 | * positive dentry isn't good idea. So it's unsupported like | ||
| 63 | * rename("filename", "FILENAME") for now. | ||
| 64 | */ | ||
| 65 | if (dentry->d_inode) | ||
| 66 | return 1; | ||
| 67 | |||
| 68 | /* | ||
| 69 | * This may be nfsd (or something), anyway, we can't see the | ||
| 70 | * intent of this. So, since this can be for creation, drop it. | ||
| 71 | */ | ||
| 72 | if (!nd) | ||
| 73 | return 0; | ||
| 74 | |||
| 75 | /* | ||
| 76 | * Drop the negative dentry, in order to make sure to use the | ||
| 77 | * case sensitive name which is specified by user if this is | ||
| 78 | * for creation. | ||
| 79 | */ | ||
| 80 | if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) { | ||
| 81 | if (nd->flags & LOOKUP_CREATE) | ||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | return vfat_revalidate_shortname(dentry); | ||
| 86 | } | ||
| 87 | |||
| 49 | /* returns the length of a struct qstr, ignoring trailing dots */ | 88 | /* returns the length of a struct qstr, ignoring trailing dots */ |
| 50 | static unsigned int vfat_striptail_len(struct qstr *qstr) | 89 | static unsigned int vfat_striptail_len(struct qstr *qstr) |
| 51 | { | 90 | { |
| @@ -127,25 +166,16 @@ static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) | |||
| 127 | return 1; | 166 | return 1; |
| 128 | } | 167 | } |
| 129 | 168 | ||
| 130 | static struct dentry_operations vfat_dentry_ops[4] = { | 169 | static struct dentry_operations vfat_ci_dentry_ops = { |
| 131 | { | 170 | .d_revalidate = vfat_revalidate_ci, |
| 132 | .d_hash = vfat_hashi, | 171 | .d_hash = vfat_hashi, |
| 133 | .d_compare = vfat_cmpi, | 172 | .d_compare = vfat_cmpi, |
| 134 | }, | 173 | }; |
| 135 | { | 174 | |
| 136 | .d_revalidate = vfat_revalidate, | 175 | static struct dentry_operations vfat_dentry_ops = { |
| 137 | .d_hash = vfat_hashi, | 176 | .d_revalidate = vfat_revalidate, |
| 138 | .d_compare = vfat_cmpi, | 177 | .d_hash = vfat_hash, |
| 139 | }, | 178 | .d_compare = vfat_cmp, |
| 140 | { | ||
| 141 | .d_hash = vfat_hash, | ||
| 142 | .d_compare = vfat_cmp, | ||
| 143 | }, | ||
| 144 | { | ||
| 145 | .d_revalidate = vfat_revalidate, | ||
| 146 | .d_hash = vfat_hash, | ||
| 147 | .d_compare = vfat_cmp, | ||
| 148 | } | ||
| 149 | }; | 179 | }; |
| 150 | 180 | ||
| 151 | /* Characters that are undesirable in an MS-DOS file name */ | 181 | /* Characters that are undesirable in an MS-DOS file name */ |
| @@ -569,6 +599,7 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name, | |||
| 569 | unsigned char msdos_name[MSDOS_NAME]; | 599 | unsigned char msdos_name[MSDOS_NAME]; |
| 570 | wchar_t *uname; | 600 | wchar_t *uname; |
| 571 | __le16 time, date; | 601 | __le16 time, date; |
| 602 | u8 time_cs; | ||
| 572 | int err, ulen, usize, i; | 603 | int err, ulen, usize, i; |
| 573 | loff_t offset; | 604 | loff_t offset; |
| 574 | 605 | ||
| @@ -621,10 +652,10 @@ shortname: | |||
| 621 | memcpy(de->name, msdos_name, MSDOS_NAME); | 652 | memcpy(de->name, msdos_name, MSDOS_NAME); |
| 622 | de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; | 653 | de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; |
| 623 | de->lcase = lcase; | 654 | de->lcase = lcase; |
| 624 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); | 655 | fat_time_unix2fat(sbi, ts, &time, &date, &time_cs); |
| 625 | de->time = de->ctime = time; | 656 | de->time = de->ctime = time; |
| 626 | de->date = de->cdate = de->adate = date; | 657 | de->date = de->cdate = de->adate = date; |
| 627 | de->ctime_cs = 0; | 658 | de->ctime_cs = time_cs; |
| 628 | de->start = cpu_to_le16(cluster); | 659 | de->start = cpu_to_le16(cluster); |
| 629 | de->starthi = cpu_to_le16(cluster >> 16); | 660 | de->starthi = cpu_to_le16(cluster >> 16); |
| 630 | de->size = 0; | 661 | de->size = 0; |
| @@ -683,46 +714,58 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, | |||
| 683 | { | 714 | { |
| 684 | struct super_block *sb = dir->i_sb; | 715 | struct super_block *sb = dir->i_sb; |
| 685 | struct fat_slot_info sinfo; | 716 | struct fat_slot_info sinfo; |
| 686 | struct inode *inode = NULL; | 717 | struct inode *inode; |
| 687 | struct dentry *alias; | 718 | struct dentry *alias; |
| 688 | int err, table; | 719 | int err; |
| 689 | 720 | ||
| 690 | lock_super(sb); | 721 | lock_super(sb); |
| 691 | table = (MSDOS_SB(sb)->options.name_check == 's') ? 2 : 0; | ||
| 692 | dentry->d_op = &vfat_dentry_ops[table]; | ||
| 693 | 722 | ||
| 694 | err = vfat_find(dir, &dentry->d_name, &sinfo); | 723 | err = vfat_find(dir, &dentry->d_name, &sinfo); |
| 695 | if (err) { | 724 | if (err) { |
| 696 | table++; | 725 | if (err == -ENOENT) { |
| 726 | inode = NULL; | ||
| 727 | goto out; | ||
| 728 | } | ||
| 697 | goto error; | 729 | goto error; |
| 698 | } | 730 | } |
| 731 | |||
| 699 | inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); | 732 | inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); |
| 700 | brelse(sinfo.bh); | 733 | brelse(sinfo.bh); |
| 701 | if (IS_ERR(inode)) { | 734 | if (IS_ERR(inode)) { |
| 702 | unlock_super(sb); | 735 | err = PTR_ERR(inode); |
| 703 | return ERR_CAST(inode); | 736 | goto error; |
| 704 | } | 737 | } |
| 705 | alias = d_find_alias(inode); | ||
| 706 | if (alias) { | ||
| 707 | if (d_invalidate(alias) == 0) | ||
| 708 | dput(alias); | ||
| 709 | else { | ||
| 710 | iput(inode); | ||
| 711 | unlock_super(sb); | ||
| 712 | return alias; | ||
| 713 | } | ||
| 714 | 738 | ||
| 739 | alias = d_find_alias(inode); | ||
| 740 | if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) { | ||
| 741 | /* | ||
| 742 | * This inode has non DCACHE_DISCONNECTED dentry. This | ||
| 743 | * means, the user did ->lookup() by an another name | ||
| 744 | * (longname vs 8.3 alias of it) in past. | ||
| 745 | * | ||
| 746 | * Switch to new one for reason of locality if possible. | ||
| 747 | */ | ||
| 748 | BUG_ON(d_unhashed(alias)); | ||
| 749 | if (!S_ISDIR(inode->i_mode)) | ||
| 750 | d_move(alias, dentry); | ||
| 751 | iput(inode); | ||
| 752 | unlock_super(sb); | ||
| 753 | return alias; | ||
| 715 | } | 754 | } |
| 716 | error: | 755 | out: |
| 717 | unlock_super(sb); | 756 | unlock_super(sb); |
| 718 | dentry->d_op = &vfat_dentry_ops[table]; | 757 | dentry->d_op = sb->s_root->d_op; |
| 719 | dentry->d_time = dentry->d_parent->d_inode->i_version; | 758 | dentry->d_time = dentry->d_parent->d_inode->i_version; |
| 720 | dentry = d_splice_alias(inode, dentry); | 759 | dentry = d_splice_alias(inode, dentry); |
| 721 | if (dentry) { | 760 | if (dentry) { |
| 722 | dentry->d_op = &vfat_dentry_ops[table]; | 761 | dentry->d_op = sb->s_root->d_op; |
| 723 | dentry->d_time = dentry->d_parent->d_inode->i_version; | 762 | dentry->d_time = dentry->d_parent->d_inode->i_version; |
| 724 | } | 763 | } |
| 725 | return dentry; | 764 | return dentry; |
| 765 | |||
| 766 | error: | ||
| 767 | unlock_super(sb); | ||
| 768 | return ERR_PTR(err); | ||
| 726 | } | 769 | } |
| 727 | 770 | ||
| 728 | static int vfat_create(struct inode *dir, struct dentry *dentry, int mode, | 771 | static int vfat_create(struct inode *dir, struct dentry *dentry, int mode, |
| @@ -1014,9 +1057,9 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1014 | return res; | 1057 | return res; |
| 1015 | 1058 | ||
| 1016 | if (MSDOS_SB(sb)->options.name_check != 's') | 1059 | if (MSDOS_SB(sb)->options.name_check != 's') |
| 1017 | sb->s_root->d_op = &vfat_dentry_ops[0]; | 1060 | sb->s_root->d_op = &vfat_ci_dentry_ops; |
| 1018 | else | 1061 | else |
| 1019 | sb->s_root->d_op = &vfat_dentry_ops[2]; | 1062 | sb->s_root->d_op = &vfat_dentry_ops; |
| 1020 | 1063 | ||
| 1021 | return 0; | 1064 | return 0; |
| 1022 | } | 1065 | } |
diff --git a/fs/file_table.c b/fs/file_table.c index efc06faede6c..5ad0eca6eea2 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
| @@ -269,6 +269,10 @@ void __fput(struct file *file) | |||
| 269 | eventpoll_release(file); | 269 | eventpoll_release(file); |
| 270 | locks_remove_flock(file); | 270 | locks_remove_flock(file); |
| 271 | 271 | ||
| 272 | if (unlikely(file->f_flags & FASYNC)) { | ||
| 273 | if (file->f_op && file->f_op->fasync) | ||
| 274 | file->f_op->fasync(-1, file, 0); | ||
| 275 | } | ||
| 272 | if (file->f_op && file->f_op->release) | 276 | if (file->f_op && file->f_op->release) |
| 273 | file->f_op->release(inode, file); | 277 | file->f_op->release(inode, file); |
| 274 | security_file_free(file); | 278 | security_file_free(file); |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 87250b6a8682..b72361479be2 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -1056,7 +1056,6 @@ static int fuse_dev_release(struct inode *inode, struct file *file) | |||
| 1056 | end_requests(fc, &fc->pending); | 1056 | end_requests(fc, &fc->pending); |
| 1057 | end_requests(fc, &fc->processing); | 1057 | end_requests(fc, &fc->processing); |
| 1058 | spin_unlock(&fc->lock); | 1058 | spin_unlock(&fc->lock); |
| 1059 | fasync_helper(-1, file, 0, &fc->fasync); | ||
| 1060 | fuse_conn_put(fc); | 1059 | fuse_conn_put(fc); |
| 1061 | } | 1060 | } |
| 1062 | 1061 | ||
diff --git a/fs/inotify_user.c b/fs/inotify_user.c index d85c7d931cdf..d367e9b92862 100644 --- a/fs/inotify_user.c +++ b/fs/inotify_user.c | |||
| @@ -537,9 +537,6 @@ static int inotify_release(struct inode *ignored, struct file *file) | |||
| 537 | inotify_dev_event_dequeue(dev); | 537 | inotify_dev_event_dequeue(dev); |
| 538 | mutex_unlock(&dev->ev_mutex); | 538 | mutex_unlock(&dev->ev_mutex); |
| 539 | 539 | ||
| 540 | if (file->f_flags & FASYNC) | ||
| 541 | inotify_fasync(-1, file, 0); | ||
| 542 | |||
| 543 | /* free this device: the put matching the get in inotify_init() */ | 540 | /* free this device: the put matching the get in inotify_init() */ |
| 544 | put_inotify_dev(dev); | 541 | put_inotify_dev(dev); |
| 545 | 542 | ||
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 1bd8d4acc6f2..61f32f3868cd 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c | |||
| @@ -115,7 +115,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
| 115 | */ | 115 | */ |
| 116 | void __log_wait_for_space(journal_t *journal) | 116 | void __log_wait_for_space(journal_t *journal) |
| 117 | { | 117 | { |
| 118 | int nblocks; | 118 | int nblocks, space_left; |
| 119 | assert_spin_locked(&journal->j_state_lock); | 119 | assert_spin_locked(&journal->j_state_lock); |
| 120 | 120 | ||
| 121 | nblocks = jbd_space_needed(journal); | 121 | nblocks = jbd_space_needed(journal); |
| @@ -128,25 +128,42 @@ void __log_wait_for_space(journal_t *journal) | |||
| 128 | /* | 128 | /* |
| 129 | * Test again, another process may have checkpointed while we | 129 | * Test again, another process may have checkpointed while we |
| 130 | * were waiting for the checkpoint lock. If there are no | 130 | * were waiting for the checkpoint lock. If there are no |
| 131 | * outstanding transactions there is nothing to checkpoint and | 131 | * transactions ready to be checkpointed, try to recover |
| 132 | * we can't make progress. Abort the journal in this case. | 132 | * journal space by calling cleanup_journal_tail(), and if |
| 133 | * that doesn't work, by waiting for the currently committing | ||
| 134 | * transaction to complete. If there is absolutely no way | ||
| 135 | * to make progress, this is either a BUG or corrupted | ||
| 136 | * filesystem, so abort the journal and leave a stack | ||
| 137 | * trace for forensic evidence. | ||
| 133 | */ | 138 | */ |
| 134 | spin_lock(&journal->j_state_lock); | 139 | spin_lock(&journal->j_state_lock); |
| 135 | spin_lock(&journal->j_list_lock); | 140 | spin_lock(&journal->j_list_lock); |
| 136 | nblocks = jbd_space_needed(journal); | 141 | nblocks = jbd_space_needed(journal); |
| 137 | if (__log_space_left(journal) < nblocks) { | 142 | space_left = __log_space_left(journal); |
| 143 | if (space_left < nblocks) { | ||
| 138 | int chkpt = journal->j_checkpoint_transactions != NULL; | 144 | int chkpt = journal->j_checkpoint_transactions != NULL; |
| 145 | tid_t tid = 0; | ||
| 139 | 146 | ||
| 147 | if (journal->j_committing_transaction) | ||
| 148 | tid = journal->j_committing_transaction->t_tid; | ||
| 140 | spin_unlock(&journal->j_list_lock); | 149 | spin_unlock(&journal->j_list_lock); |
| 141 | spin_unlock(&journal->j_state_lock); | 150 | spin_unlock(&journal->j_state_lock); |
| 142 | if (chkpt) { | 151 | if (chkpt) { |
| 143 | log_do_checkpoint(journal); | 152 | log_do_checkpoint(journal); |
| 153 | } else if (cleanup_journal_tail(journal) == 0) { | ||
| 154 | /* We were able to recover space; yay! */ | ||
| 155 | ; | ||
| 156 | } else if (tid) { | ||
| 157 | log_wait_commit(journal, tid); | ||
| 144 | } else { | 158 | } else { |
| 145 | printk(KERN_ERR "%s: no transactions\n", | 159 | printk(KERN_ERR "%s: needed %d blocks and " |
| 146 | __func__); | 160 | "only had %d space available\n", |
| 161 | __func__, nblocks, space_left); | ||
| 162 | printk(KERN_ERR "%s: no way to get more " | ||
| 163 | "journal space\n", __func__); | ||
| 164 | WARN_ON(1); | ||
| 147 | journal_abort(journal, 0); | 165 | journal_abort(journal, 0); |
| 148 | } | 166 | } |
| 149 | |||
| 150 | spin_lock(&journal->j_state_lock); | 167 | spin_lock(&journal->j_state_lock); |
| 151 | } else { | 168 | } else { |
| 152 | spin_unlock(&journal->j_list_lock); | 169 | spin_unlock(&journal->j_list_lock); |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index d15cd6e7251e..60d4c32c8808 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
| @@ -860,7 +860,6 @@ out: | |||
| 860 | * int journal_get_undo_access() - Notify intent to modify metadata with non-rewindable consequences | 860 | * int journal_get_undo_access() - Notify intent to modify metadata with non-rewindable consequences |
| 861 | * @handle: transaction | 861 | * @handle: transaction |
| 862 | * @bh: buffer to undo | 862 | * @bh: buffer to undo |
| 863 | * @credits: store the number of taken credits here (if not NULL) | ||
| 864 | * | 863 | * |
| 865 | * Sometimes there is a need to distinguish between metadata which has | 864 | * Sometimes there is a need to distinguish between metadata which has |
| 866 | * been committed to disk and that which has not. The ext3fs code uses | 865 | * been committed to disk and that which has not. The ext3fs code uses |
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 9203c3332f17..9497718fe920 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
| @@ -116,7 +116,7 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
| 116 | */ | 116 | */ |
| 117 | void __jbd2_log_wait_for_space(journal_t *journal) | 117 | void __jbd2_log_wait_for_space(journal_t *journal) |
| 118 | { | 118 | { |
| 119 | int nblocks; | 119 | int nblocks, space_left; |
| 120 | assert_spin_locked(&journal->j_state_lock); | 120 | assert_spin_locked(&journal->j_state_lock); |
| 121 | 121 | ||
| 122 | nblocks = jbd_space_needed(journal); | 122 | nblocks = jbd_space_needed(journal); |
| @@ -129,25 +129,43 @@ void __jbd2_log_wait_for_space(journal_t *journal) | |||
| 129 | /* | 129 | /* |
| 130 | * Test again, another process may have checkpointed while we | 130 | * Test again, another process may have checkpointed while we |
| 131 | * were waiting for the checkpoint lock. If there are no | 131 | * were waiting for the checkpoint lock. If there are no |
| 132 | * outstanding transactions there is nothing to checkpoint and | 132 | * transactions ready to be checkpointed, try to recover |
| 133 | * we can't make progress. Abort the journal in this case. | 133 | * journal space by calling cleanup_journal_tail(), and if |
| 134 | * that doesn't work, by waiting for the currently committing | ||
| 135 | * transaction to complete. If there is absolutely no way | ||
| 136 | * to make progress, this is either a BUG or corrupted | ||
| 137 | * filesystem, so abort the journal and leave a stack | ||
| 138 | * trace for forensic evidence. | ||
| 134 | */ | 139 | */ |
| 135 | spin_lock(&journal->j_state_lock); | 140 | spin_lock(&journal->j_state_lock); |
| 136 | spin_lock(&journal->j_list_lock); | 141 | spin_lock(&journal->j_list_lock); |
| 137 | nblocks = jbd_space_needed(journal); | 142 | nblocks = jbd_space_needed(journal); |
| 138 | if (__jbd2_log_space_left(journal) < nblocks) { | 143 | space_left = __jbd2_log_space_left(journal); |
| 144 | if (space_left < nblocks) { | ||
| 139 | int chkpt = journal->j_checkpoint_transactions != NULL; | 145 | int chkpt = journal->j_checkpoint_transactions != NULL; |
| 146 | tid_t tid = 0; | ||
| 140 | 147 | ||
| 148 | if (journal->j_committing_transaction) | ||
| 149 | tid = journal->j_committing_transaction->t_tid; | ||
| 141 | spin_unlock(&journal->j_list_lock); | 150 | spin_unlock(&journal->j_list_lock); |
| 142 | spin_unlock(&journal->j_state_lock); | 151 | spin_unlock(&journal->j_state_lock); |
| 143 | if (chkpt) { | 152 | if (chkpt) { |
| 144 | jbd2_log_do_checkpoint(journal); | 153 | jbd2_log_do_checkpoint(journal); |
| 154 | } else if (jbd2_cleanup_journal_tail(journal) == 0) { | ||
| 155 | /* We were able to recover space; yay! */ | ||
| 156 | ; | ||
| 157 | } else if (tid) { | ||
| 158 | jbd2_log_wait_commit(journal, tid); | ||
| 145 | } else { | 159 | } else { |
| 146 | printk(KERN_ERR "%s: no transactions\n", | 160 | printk(KERN_ERR "%s: needed %d blocks and " |
| 147 | __func__); | 161 | "only had %d space available\n", |
| 162 | __func__, nblocks, space_left); | ||
| 163 | printk(KERN_ERR "%s: no way to get more " | ||
| 164 | "journal space in %s\n", __func__, | ||
| 165 | journal->j_devname); | ||
| 166 | WARN_ON(1); | ||
| 148 | jbd2_journal_abort(journal, 0); | 167 | jbd2_journal_abort(journal, 0); |
| 149 | } | 168 | } |
| 150 | |||
| 151 | spin_lock(&journal->j_state_lock); | 169 | spin_lock(&journal->j_state_lock); |
| 152 | } else { | 170 | } else { |
| 153 | spin_unlock(&journal->j_list_lock); | 171 | spin_unlock(&journal->j_list_lock); |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 8b119e16aa36..ebc667bc54a8 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -974,6 +974,9 @@ restart_loop: | |||
| 974 | journal->j_committing_transaction = NULL; | 974 | journal->j_committing_transaction = NULL; |
| 975 | spin_unlock(&journal->j_state_lock); | 975 | spin_unlock(&journal->j_state_lock); |
| 976 | 976 | ||
| 977 | if (journal->j_commit_callback) | ||
| 978 | journal->j_commit_callback(journal, commit_transaction); | ||
| 979 | |||
| 977 | if (commit_transaction->t_checkpoint_list == NULL && | 980 | if (commit_transaction->t_checkpoint_list == NULL && |
| 978 | commit_transaction->t_checkpoint_io_list == NULL) { | 981 | commit_transaction->t_checkpoint_io_list == NULL) { |
| 979 | __jbd2_journal_drop_transaction(journal, commit_transaction); | 982 | __jbd2_journal_drop_transaction(journal, commit_transaction); |
| @@ -995,11 +998,8 @@ restart_loop: | |||
| 995 | } | 998 | } |
| 996 | spin_unlock(&journal->j_list_lock); | 999 | spin_unlock(&journal->j_list_lock); |
| 997 | 1000 | ||
| 998 | if (journal->j_commit_callback) | ||
| 999 | journal->j_commit_callback(journal, commit_transaction); | ||
| 1000 | |||
| 1001 | trace_mark(jbd2_end_commit, "dev %s transaction %d head %d", | 1001 | trace_mark(jbd2_end_commit, "dev %s transaction %d head %d", |
| 1002 | journal->j_devname, commit_transaction->t_tid, | 1002 | journal->j_devname, journal->j_commit_sequence, |
| 1003 | journal->j_tail_sequence); | 1003 | journal->j_tail_sequence); |
| 1004 | jbd_debug(1, "JBD: commit %d complete, head %d\n", | 1004 | jbd_debug(1, "JBD: commit %d complete, head %d\n", |
| 1005 | journal->j_commit_sequence, journal->j_tail_sequence); | 1005 | journal->j_commit_sequence, journal->j_tail_sequence); |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 783de118de92..e70d657a19f8 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -1089,6 +1089,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
| 1089 | if (!journal->j_wbuf) { | 1089 | if (!journal->j_wbuf) { |
| 1090 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 1090 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
| 1091 | __func__); | 1091 | __func__); |
| 1092 | jbd2_stats_proc_exit(journal); | ||
| 1092 | kfree(journal); | 1093 | kfree(journal); |
| 1093 | return NULL; | 1094 | return NULL; |
| 1094 | } | 1095 | } |
| @@ -1098,6 +1099,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) | |||
| 1098 | if (err) { | 1099 | if (err) { |
| 1099 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", | 1100 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", |
| 1100 | __func__); | 1101 | __func__); |
| 1102 | jbd2_stats_proc_exit(journal); | ||
| 1101 | kfree(journal); | 1103 | kfree(journal); |
| 1102 | return NULL; | 1104 | return NULL; |
| 1103 | } | 1105 | } |
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 8adebd3e43c6..3cceef4ad2b7 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c | |||
| @@ -85,15 +85,15 @@ static int jffs2_garbage_collect_thread(void *_c) | |||
| 85 | for (;;) { | 85 | for (;;) { |
| 86 | allow_signal(SIGHUP); | 86 | allow_signal(SIGHUP); |
| 87 | again: | 87 | again: |
| 88 | spin_lock(&c->erase_completion_lock); | ||
| 88 | if (!jffs2_thread_should_wake(c)) { | 89 | if (!jffs2_thread_should_wake(c)) { |
| 89 | set_current_state (TASK_INTERRUPTIBLE); | 90 | set_current_state (TASK_INTERRUPTIBLE); |
| 91 | spin_unlock(&c->erase_completion_lock); | ||
| 90 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); | 92 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); |
| 91 | /* Yes, there's a race here; we checked jffs2_thread_should_wake() | ||
| 92 | before setting current->state to TASK_INTERRUPTIBLE. But it doesn't | ||
| 93 | matter - We don't care if we miss a wakeup, because the GC thread | ||
| 94 | is only an optimisation anyway. */ | ||
| 95 | schedule(); | 93 | schedule(); |
| 96 | } | 94 | } else |
| 95 | spin_unlock(&c->erase_completion_lock); | ||
| 96 | |||
| 97 | 97 | ||
| 98 | /* This thread is purely an optimisation. But if it runs when | 98 | /* This thread is purely an optimisation. But if it runs when |
| 99 | other things could be running, it actually makes things a | 99 | other things could be running, it actually makes things a |
diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c index 47b045797e42..90cb60d09787 100644 --- a/fs/jffs2/compr_lzo.c +++ b/fs/jffs2/compr_lzo.c | |||
| @@ -19,7 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | static void *lzo_mem; | 20 | static void *lzo_mem; |
| 21 | static void *lzo_compress_buf; | 21 | static void *lzo_compress_buf; |
| 22 | static DEFINE_MUTEX(deflate_mutex); | 22 | static DEFINE_MUTEX(deflate_mutex); /* for lzo_mem and lzo_compress_buf */ |
| 23 | 23 | ||
| 24 | static void free_workspace(void) | 24 | static void free_workspace(void) |
| 25 | { | 25 | { |
| @@ -49,18 +49,21 @@ static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, | |||
| 49 | 49 | ||
| 50 | mutex_lock(&deflate_mutex); | 50 | mutex_lock(&deflate_mutex); |
| 51 | ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem); | 51 | ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem); |
| 52 | mutex_unlock(&deflate_mutex); | ||
| 53 | |||
| 54 | if (ret != LZO_E_OK) | 52 | if (ret != LZO_E_OK) |
| 55 | return -1; | 53 | goto fail; |
| 56 | 54 | ||
| 57 | if (compress_size > *dstlen) | 55 | if (compress_size > *dstlen) |
| 58 | return -1; | 56 | goto fail; |
| 59 | 57 | ||
| 60 | memcpy(cpage_out, lzo_compress_buf, compress_size); | 58 | memcpy(cpage_out, lzo_compress_buf, compress_size); |
| 61 | *dstlen = compress_size; | 59 | mutex_unlock(&deflate_mutex); |
| 62 | 60 | ||
| 61 | *dstlen = compress_size; | ||
| 63 | return 0; | 62 | return 0; |
| 63 | |||
| 64 | fail: | ||
| 65 | mutex_unlock(&deflate_mutex); | ||
| 66 | return -1; | ||
| 64 | } | 67 | } |
| 65 | 68 | ||
| 66 | static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, | 69 | static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, |
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 0875b60b4bf7..21a052915aa9 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
| @@ -261,9 +261,11 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) | |||
| 261 | 261 | ||
| 262 | jffs2_sum_reset_collected(c->summary); /* reset collected summary */ | 262 | jffs2_sum_reset_collected(c->summary); /* reset collected summary */ |
| 263 | 263 | ||
| 264 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | ||
| 264 | /* adjust write buffer offset, else we get a non contiguous write bug */ | 265 | /* adjust write buffer offset, else we get a non contiguous write bug */ |
| 265 | if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len) | 266 | if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len) |
| 266 | c->wbuf_ofs = 0xffffffff; | 267 | c->wbuf_ofs = 0xffffffff; |
| 268 | #endif | ||
| 267 | 269 | ||
| 268 | D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); | 270 | D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); |
| 269 | 271 | ||
diff --git a/fs/libfs.c b/fs/libfs.c index 74688598bcf7..e960a8321902 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
| @@ -814,7 +814,7 @@ EXPORT_SYMBOL(simple_getattr); | |||
| 814 | EXPORT_SYMBOL(simple_link); | 814 | EXPORT_SYMBOL(simple_link); |
| 815 | EXPORT_SYMBOL(simple_lookup); | 815 | EXPORT_SYMBOL(simple_lookup); |
| 816 | EXPORT_SYMBOL(simple_pin_fs); | 816 | EXPORT_SYMBOL(simple_pin_fs); |
| 817 | EXPORT_SYMBOL(simple_prepare_write); | 817 | EXPORT_UNUSED_SYMBOL(simple_prepare_write); |
| 818 | EXPORT_SYMBOL(simple_readpage); | 818 | EXPORT_SYMBOL(simple_readpage); |
| 819 | EXPORT_SYMBOL(simple_release_fs); | 819 | EXPORT_SYMBOL(simple_release_fs); |
| 820 | EXPORT_SYMBOL(simple_rename); | 820 | EXPORT_SYMBOL(simple_rename); |
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 014f6ce48172..4dfdcbc6bf68 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c | |||
| @@ -434,6 +434,7 @@ nlm4svc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, | |||
| 434 | * reclaim all locks we hold on this server. | 434 | * reclaim all locks we hold on this server. |
| 435 | */ | 435 | */ |
| 436 | memset(&saddr, 0, sizeof(saddr)); | 436 | memset(&saddr, 0, sizeof(saddr)); |
| 437 | saddr.sin_family = AF_INET; | ||
| 437 | saddr.sin_addr.s_addr = argp->addr; | 438 | saddr.sin_addr.s_addr = argp->addr; |
| 438 | nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); | 439 | nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); |
| 439 | 440 | ||
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 548b0bb2b84d..3ca89e2a9381 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
| @@ -466,6 +466,7 @@ nlmsvc_proc_sm_notify(struct svc_rqst *rqstp, struct nlm_reboot *argp, | |||
| 466 | * reclaim all locks we hold on this server. | 466 | * reclaim all locks we hold on this server. |
| 467 | */ | 467 | */ |
| 468 | memset(&saddr, 0, sizeof(saddr)); | 468 | memset(&saddr, 0, sizeof(saddr)); |
| 469 | saddr.sin_family = AF_INET; | ||
| 469 | saddr.sin_addr.s_addr = argp->addr; | 470 | saddr.sin_addr.s_addr = argp->addr; |
| 470 | nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); | 471 | nlm_host_rebooted(&saddr, argp->mon, argp->len, argp->state); |
| 471 | 472 | ||
diff --git a/fs/msdos/Makefile b/fs/msdos/Makefile deleted file mode 100644 index ea67646fcb95..000000000000 --- a/fs/msdos/Makefile +++ /dev/null | |||
| @@ -1,7 +0,0 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the Linux msdos filesystem routines. | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_MSDOS_FS) += msdos.o | ||
| 6 | |||
| 7 | msdos-y := namei.o | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index dc52793ff8f8..d22eb383e1cf 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -908,21 +908,16 @@ static int nfs_size_need_update(const struct inode *inode, const struct nfs_fatt | |||
| 908 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); | 908 | return nfs_size_to_loff_t(fattr->size) > i_size_read(inode); |
| 909 | } | 909 | } |
| 910 | 910 | ||
| 911 | static unsigned long nfs_attr_generation_counter; | 911 | static atomic_long_t nfs_attr_generation_counter; |
| 912 | 912 | ||
| 913 | static unsigned long nfs_read_attr_generation_counter(void) | 913 | static unsigned long nfs_read_attr_generation_counter(void) |
| 914 | { | 914 | { |
| 915 | smp_rmb(); | 915 | return atomic_long_read(&nfs_attr_generation_counter); |
| 916 | return nfs_attr_generation_counter; | ||
| 917 | } | 916 | } |
| 918 | 917 | ||
| 919 | unsigned long nfs_inc_attr_generation_counter(void) | 918 | unsigned long nfs_inc_attr_generation_counter(void) |
| 920 | { | 919 | { |
| 921 | unsigned long ret; | 920 | return atomic_long_inc_return(&nfs_attr_generation_counter); |
| 922 | smp_rmb(); | ||
| 923 | ret = ++nfs_attr_generation_counter; | ||
| 924 | smp_wmb(); | ||
| 925 | return ret; | ||
| 926 | } | 921 | } |
| 927 | 922 | ||
| 928 | void nfs_fattr_init(struct nfs_fattr *fattr) | 923 | void nfs_fattr_init(struct nfs_fattr *fattr) |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 0bc56f6d9276..4433c8f00163 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -1875,11 +1875,11 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, | |||
| 1875 | return -ENOMEM; | 1875 | return -ENOMEM; |
| 1876 | 1876 | ||
| 1877 | offset = *offsetp; | 1877 | offset = *offsetp; |
| 1878 | cdp->err = nfserr_eof; /* will be cleared on successful read */ | ||
| 1879 | 1878 | ||
| 1880 | while (1) { | 1879 | while (1) { |
| 1881 | unsigned int reclen; | 1880 | unsigned int reclen; |
| 1882 | 1881 | ||
| 1882 | cdp->err = nfserr_eof; /* will be cleared on successful read */ | ||
| 1883 | buf.used = 0; | 1883 | buf.used = 0; |
| 1884 | buf.full = 0; | 1884 | buf.full = 0; |
| 1885 | 1885 | ||
| @@ -1912,8 +1912,6 @@ static int nfsd_buffered_readdir(struct file *file, filldir_t func, | |||
| 1912 | de = (struct buffered_dirent *)((char *)de + reclen); | 1912 | de = (struct buffered_dirent *)((char *)de + reclen); |
| 1913 | } | 1913 | } |
| 1914 | offset = vfs_llseek(file, 0, SEEK_CUR); | 1914 | offset = vfs_llseek(file, 0, SEEK_CUR); |
| 1915 | if (!buf.full) | ||
| 1916 | break; | ||
| 1917 | } | 1915 | } |
| 1918 | 1916 | ||
| 1919 | done: | 1917 | done: |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 8d3225a78073..7efe937a415f 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -679,8 +679,7 @@ leave: | |||
| 679 | 679 | ||
| 680 | /* Some parts of this taken from generic_cont_expand, which turned out | 680 | /* Some parts of this taken from generic_cont_expand, which turned out |
| 681 | * to be too fragile to do exactly what we need without us having to | 681 | * to be too fragile to do exactly what we need without us having to |
| 682 | * worry about recursive locking in ->prepare_write() and | 682 | * worry about recursive locking in ->write_begin() and ->write_end(). */ |
| 683 | * ->commit_write(). */ | ||
| 684 | static int ocfs2_write_zero_page(struct inode *inode, | 683 | static int ocfs2_write_zero_page(struct inode *inode, |
| 685 | u64 size) | 684 | u64 size) |
| 686 | { | 685 | { |
| @@ -717,14 +717,12 @@ pipe_rdwr_fasync(int fd, struct file *filp, int on) | |||
| 717 | static int | 717 | static int |
| 718 | pipe_read_release(struct inode *inode, struct file *filp) | 718 | pipe_read_release(struct inode *inode, struct file *filp) |
| 719 | { | 719 | { |
| 720 | pipe_read_fasync(-1, filp, 0); | ||
| 721 | return pipe_release(inode, 1, 0); | 720 | return pipe_release(inode, 1, 0); |
| 722 | } | 721 | } |
| 723 | 722 | ||
| 724 | static int | 723 | static int |
| 725 | pipe_write_release(struct inode *inode, struct file *filp) | 724 | pipe_write_release(struct inode *inode, struct file *filp) |
| 726 | { | 725 | { |
| 727 | pipe_write_fasync(-1, filp, 0); | ||
| 728 | return pipe_release(inode, 0, 1); | 726 | return pipe_release(inode, 0, 1); |
| 729 | } | 727 | } |
| 730 | 728 | ||
| @@ -733,7 +731,6 @@ pipe_rdwr_release(struct inode *inode, struct file *filp) | |||
| 733 | { | 731 | { |
| 734 | int decr, decw; | 732 | int decr, decw; |
| 735 | 733 | ||
| 736 | pipe_rdwr_fasync(-1, filp, 0); | ||
| 737 | decr = (filp->f_mode & FMODE_READ) != 0; | 734 | decr = (filp->f_mode & FMODE_READ) != 0; |
| 738 | decw = (filp->f_mode & FMODE_WRITE) != 0; | 735 | decw = (filp->f_mode & FMODE_WRITE) != 0; |
| 739 | return pipe_release(inode, decr, decw); | 736 | return pipe_release(inode, decr, decw); |
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c index 0c10a0b3f146..df26aa88fa47 100644 --- a/fs/proc/uptime.c +++ b/fs/proc/uptime.c | |||
| @@ -1,43 +1,45 @@ | |||
| 1 | #include <linux/fs.h> | ||
| 2 | #include <linux/init.h> | 1 | #include <linux/init.h> |
| 3 | #include <linux/proc_fs.h> | 2 | #include <linux/proc_fs.h> |
| 4 | #include <linux/sched.h> | 3 | #include <linux/sched.h> |
| 5 | #include <linux/seq_file.h> | ||
| 6 | #include <linux/time.h> | 4 | #include <linux/time.h> |
| 7 | #include <asm/cputime.h> | 5 | #include <asm/cputime.h> |
| 8 | 6 | ||
| 9 | static int uptime_proc_show(struct seq_file *m, void *v) | 7 | static int proc_calc_metrics(char *page, char **start, off_t off, |
| 8 | int count, int *eof, int len) | ||
| 9 | { | ||
| 10 | if (len <= off + count) | ||
| 11 | *eof = 1; | ||
| 12 | *start = page + off; | ||
| 13 | len -= off; | ||
| 14 | if (len > count) | ||
| 15 | len = count; | ||
| 16 | if (len < 0) | ||
| 17 | len = 0; | ||
| 18 | return len; | ||
| 19 | } | ||
| 20 | |||
| 21 | static int uptime_read_proc(char *page, char **start, off_t off, int count, | ||
| 22 | int *eof, void *data) | ||
| 10 | { | 23 | { |
| 11 | struct timespec uptime; | 24 | struct timespec uptime; |
| 12 | struct timespec idle; | 25 | struct timespec idle; |
| 26 | int len; | ||
| 13 | cputime_t idletime = cputime_add(init_task.utime, init_task.stime); | 27 | cputime_t idletime = cputime_add(init_task.utime, init_task.stime); |
| 14 | 28 | ||
| 15 | do_posix_clock_monotonic_gettime(&uptime); | 29 | do_posix_clock_monotonic_gettime(&uptime); |
| 16 | monotonic_to_bootbased(&uptime); | 30 | monotonic_to_bootbased(&uptime); |
| 17 | cputime_to_timespec(idletime, &idle); | 31 | cputime_to_timespec(idletime, &idle); |
| 18 | seq_printf(m, "%lu.%02lu %lu.%02lu\n", | 32 | len = sprintf(page, "%lu.%02lu %lu.%02lu\n", |
| 19 | (unsigned long) uptime.tv_sec, | 33 | (unsigned long) uptime.tv_sec, |
| 20 | (uptime.tv_nsec / (NSEC_PER_SEC / 100)), | 34 | (uptime.tv_nsec / (NSEC_PER_SEC / 100)), |
| 21 | (unsigned long) idle.tv_sec, | 35 | (unsigned long) idle.tv_sec, |
| 22 | (idle.tv_nsec / (NSEC_PER_SEC / 100))); | 36 | (idle.tv_nsec / (NSEC_PER_SEC / 100))); |
| 23 | return 0; | 37 | return proc_calc_metrics(page, start, off, count, eof, len); |
| 24 | } | 38 | } |
| 25 | 39 | ||
| 26 | static int uptime_proc_open(struct inode *inode, struct file *file) | ||
| 27 | { | ||
| 28 | return single_open(file, uptime_proc_show, NULL); | ||
| 29 | } | ||
| 30 | |||
| 31 | static const struct file_operations uptime_proc_fops = { | ||
| 32 | .open = uptime_proc_open, | ||
| 33 | .read = seq_read, | ||
| 34 | .llseek = seq_lseek, | ||
| 35 | .release = single_release, | ||
| 36 | }; | ||
| 37 | |||
| 38 | static int __init proc_uptime_init(void) | 40 | static int __init proc_uptime_init(void) |
| 39 | { | 41 | { |
| 40 | proc_create("uptime", 0, NULL, &uptime_proc_fops); | 42 | create_proc_read_entry("uptime", 0, NULL, uptime_read_proc, NULL); |
| 41 | return 0; | 43 | return 0; |
| 42 | } | 44 | } |
| 43 | module_init(proc_uptime_init); | 45 | module_init(proc_uptime_init); |
diff --git a/fs/splice.c b/fs/splice.c index a1e701c27156..1abab5cee4ba 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -731,8 +731,8 @@ ssize_t splice_from_pipe(struct pipe_inode_info *pipe, struct file *out, | |||
| 731 | }; | 731 | }; |
| 732 | 732 | ||
| 733 | /* | 733 | /* |
| 734 | * The actor worker might be calling ->prepare_write and | 734 | * The actor worker might be calling ->write_begin and |
| 735 | * ->commit_write. Most of the time, these expect i_mutex to | 735 | * ->write_end. Most of the time, these expect i_mutex to |
| 736 | * be held. Since this may result in an ABBA deadlock with | 736 | * be held. Since this may result in an ABBA deadlock with |
| 737 | * pipe->inode, we have to order lock acquiry here. | 737 | * pipe->inode, we have to order lock acquiry here. |
| 738 | */ | 738 | */ |
diff --git a/fs/vfat/Makefile b/fs/vfat/Makefile deleted file mode 100644 index 40f2798a4f08..000000000000 --- a/fs/vfat/Makefile +++ /dev/null | |||
| @@ -1,7 +0,0 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the linux vfat-filesystem routines. | ||
| 3 | # | ||
| 4 | |||
| 5 | obj-$(CONFIG_VFAT_FS) += vfat.o | ||
| 6 | |||
| 7 | vfat-y := namei.o | ||
