diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bio.c | 10 | ||||
-rw-r--r-- | fs/ceph/caps.c | 4 | ||||
-rw-r--r-- | fs/ceph/dir.c | 4 | ||||
-rw-r--r-- | fs/ceph/mds_client.c | 10 | ||||
-rw-r--r-- | fs/ceph/mds_client.h | 7 | ||||
-rw-r--r-- | fs/ceph/xattr.c | 4 | ||||
-rw-r--r-- | fs/cifs/Kconfig | 4 | ||||
-rw-r--r-- | fs/cifs/connect.c | 23 | ||||
-rw-r--r-- | fs/cifs/dir.c | 2 | ||||
-rw-r--r-- | fs/cifs/sess.c | 11 | ||||
-rw-r--r-- | fs/ecryptfs/crypto.c | 68 | ||||
-rw-r--r-- | fs/ecryptfs/ecryptfs_kernel.h | 6 | ||||
-rw-r--r-- | fs/ecryptfs/inode.c | 2 | ||||
-rw-r--r-- | fs/ecryptfs/keystore.c | 9 | ||||
-rw-r--r-- | fs/ecryptfs/mmap.c | 4 | ||||
-rw-r--r-- | fs/ecryptfs/read_write.c | 4 | ||||
-rw-r--r-- | fs/ecryptfs/super.c | 14 | ||||
-rw-r--r-- | fs/exec.c | 33 | ||||
-rw-r--r-- | fs/fs-writeback.c | 16 | ||||
-rw-r--r-- | fs/ioprio.c | 2 | ||||
-rw-r--r-- | fs/jffs2/erase.c | 2 | ||||
-rw-r--r-- | fs/logfs/dev_mtd.c | 6 | ||||
-rw-r--r-- | fs/nilfs2/ioctl.c | 2 | ||||
-rw-r--r-- | fs/proc/base.c | 126 | ||||
-rw-r--r-- | fs/xfs/kmem.h | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_dquot.c | 103 | ||||
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_qm.c | 291 | ||||
-rw-r--r-- | fs/xfs/xfs_qm.h | 14 | ||||
-rw-r--r-- | fs/xfs/xfs_qm_stats.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_trace.h | 5 |
31 files changed, 349 insertions, 449 deletions
@@ -505,13 +505,9 @@ EXPORT_SYMBOL(bio_clone); | |||
505 | int bio_get_nr_vecs(struct block_device *bdev) | 505 | int bio_get_nr_vecs(struct block_device *bdev) |
506 | { | 506 | { |
507 | struct request_queue *q = bdev_get_queue(bdev); | 507 | struct request_queue *q = bdev_get_queue(bdev); |
508 | int nr_pages; | 508 | return min_t(unsigned, |
509 | 509 | queue_max_segments(q), | |
510 | nr_pages = ((queue_max_sectors(q) << 9) + PAGE_SIZE - 1) >> PAGE_SHIFT; | 510 | queue_max_sectors(q) / (PAGE_SIZE >> 9) + 1); |
511 | if (nr_pages > queue_max_segments(q)) | ||
512 | nr_pages = queue_max_segments(q); | ||
513 | |||
514 | return nr_pages; | ||
515 | } | 511 | } |
516 | EXPORT_SYMBOL(bio_get_nr_vecs); | 512 | EXPORT_SYMBOL(bio_get_nr_vecs); |
517 | 513 | ||
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index b60fc8bfb3e9..620daad201db 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c | |||
@@ -641,10 +641,10 @@ static int __cap_is_valid(struct ceph_cap *cap) | |||
641 | unsigned long ttl; | 641 | unsigned long ttl; |
642 | u32 gen; | 642 | u32 gen; |
643 | 643 | ||
644 | spin_lock(&cap->session->s_cap_lock); | 644 | spin_lock(&cap->session->s_gen_ttl_lock); |
645 | gen = cap->session->s_cap_gen; | 645 | gen = cap->session->s_cap_gen; |
646 | ttl = cap->session->s_cap_ttl; | 646 | ttl = cap->session->s_cap_ttl; |
647 | spin_unlock(&cap->session->s_cap_lock); | 647 | spin_unlock(&cap->session->s_gen_ttl_lock); |
648 | 648 | ||
649 | if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) { | 649 | if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) { |
650 | dout("__cap_is_valid %p cap %p issued %s " | 650 | dout("__cap_is_valid %p cap %p issued %s " |
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 618246bc2196..3e8094be4604 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c | |||
@@ -975,10 +975,10 @@ static int dentry_lease_is_valid(struct dentry *dentry) | |||
975 | di = ceph_dentry(dentry); | 975 | di = ceph_dentry(dentry); |
976 | if (di->lease_session) { | 976 | if (di->lease_session) { |
977 | s = di->lease_session; | 977 | s = di->lease_session; |
978 | spin_lock(&s->s_cap_lock); | 978 | spin_lock(&s->s_gen_ttl_lock); |
979 | gen = s->s_cap_gen; | 979 | gen = s->s_cap_gen; |
980 | ttl = s->s_cap_ttl; | 980 | ttl = s->s_cap_ttl; |
981 | spin_unlock(&s->s_cap_lock); | 981 | spin_unlock(&s->s_gen_ttl_lock); |
982 | 982 | ||
983 | if (di->lease_gen == gen && | 983 | if (di->lease_gen == gen && |
984 | time_before(jiffies, dentry->d_time) && | 984 | time_before(jiffies, dentry->d_time) && |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 23ab6a3f1825..866e8d7ca37d 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -262,6 +262,7 @@ static int parse_reply_info(struct ceph_msg *msg, | |||
262 | /* trace */ | 262 | /* trace */ |
263 | ceph_decode_32_safe(&p, end, len, bad); | 263 | ceph_decode_32_safe(&p, end, len, bad); |
264 | if (len > 0) { | 264 | if (len > 0) { |
265 | ceph_decode_need(&p, end, len, bad); | ||
265 | err = parse_reply_info_trace(&p, p+len, info, features); | 266 | err = parse_reply_info_trace(&p, p+len, info, features); |
266 | if (err < 0) | 267 | if (err < 0) |
267 | goto out_bad; | 268 | goto out_bad; |
@@ -270,6 +271,7 @@ static int parse_reply_info(struct ceph_msg *msg, | |||
270 | /* extra */ | 271 | /* extra */ |
271 | ceph_decode_32_safe(&p, end, len, bad); | 272 | ceph_decode_32_safe(&p, end, len, bad); |
272 | if (len > 0) { | 273 | if (len > 0) { |
274 | ceph_decode_need(&p, end, len, bad); | ||
273 | err = parse_reply_info_extra(&p, p+len, info, features); | 275 | err = parse_reply_info_extra(&p, p+len, info, features); |
274 | if (err < 0) | 276 | if (err < 0) |
275 | goto out_bad; | 277 | goto out_bad; |
@@ -398,9 +400,11 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, | |||
398 | s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; | 400 | s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; |
399 | s->s_con.peer_name.num = cpu_to_le64(mds); | 401 | s->s_con.peer_name.num = cpu_to_le64(mds); |
400 | 402 | ||
401 | spin_lock_init(&s->s_cap_lock); | 403 | spin_lock_init(&s->s_gen_ttl_lock); |
402 | s->s_cap_gen = 0; | 404 | s->s_cap_gen = 0; |
403 | s->s_cap_ttl = 0; | 405 | s->s_cap_ttl = 0; |
406 | |||
407 | spin_lock_init(&s->s_cap_lock); | ||
404 | s->s_renew_requested = 0; | 408 | s->s_renew_requested = 0; |
405 | s->s_renew_seq = 0; | 409 | s->s_renew_seq = 0; |
406 | INIT_LIST_HEAD(&s->s_caps); | 410 | INIT_LIST_HEAD(&s->s_caps); |
@@ -2326,10 +2330,10 @@ static void handle_session(struct ceph_mds_session *session, | |||
2326 | case CEPH_SESSION_STALE: | 2330 | case CEPH_SESSION_STALE: |
2327 | pr_info("mds%d caps went stale, renewing\n", | 2331 | pr_info("mds%d caps went stale, renewing\n", |
2328 | session->s_mds); | 2332 | session->s_mds); |
2329 | spin_lock(&session->s_cap_lock); | 2333 | spin_lock(&session->s_gen_ttl_lock); |
2330 | session->s_cap_gen++; | 2334 | session->s_cap_gen++; |
2331 | session->s_cap_ttl = 0; | 2335 | session->s_cap_ttl = 0; |
2332 | spin_unlock(&session->s_cap_lock); | 2336 | spin_unlock(&session->s_gen_ttl_lock); |
2333 | send_renew_caps(mdsc, session); | 2337 | send_renew_caps(mdsc, session); |
2334 | break; | 2338 | break; |
2335 | 2339 | ||
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index a50ca0e39475..8c7c04ebb595 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h | |||
@@ -117,10 +117,13 @@ struct ceph_mds_session { | |||
117 | void *s_authorizer_buf, *s_authorizer_reply_buf; | 117 | void *s_authorizer_buf, *s_authorizer_reply_buf; |
118 | size_t s_authorizer_buf_len, s_authorizer_reply_buf_len; | 118 | size_t s_authorizer_buf_len, s_authorizer_reply_buf_len; |
119 | 119 | ||
120 | /* protected by s_cap_lock */ | 120 | /* protected by s_gen_ttl_lock */ |
121 | spinlock_t s_cap_lock; | 121 | spinlock_t s_gen_ttl_lock; |
122 | u32 s_cap_gen; /* inc each time we get mds stale msg */ | 122 | u32 s_cap_gen; /* inc each time we get mds stale msg */ |
123 | unsigned long s_cap_ttl; /* when session caps expire */ | 123 | unsigned long s_cap_ttl; /* when session caps expire */ |
124 | |||
125 | /* protected by s_cap_lock */ | ||
126 | spinlock_t s_cap_lock; | ||
124 | struct list_head s_caps; /* all caps issued by this session */ | 127 | struct list_head s_caps; /* all caps issued by this session */ |
125 | int s_nr_caps, s_trim_caps; | 128 | int s_nr_caps, s_trim_caps; |
126 | int s_num_cap_releases; | 129 | int s_num_cap_releases; |
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c index 857214ae8c08..a76f697303d9 100644 --- a/fs/ceph/xattr.c +++ b/fs/ceph/xattr.c | |||
@@ -111,8 +111,10 @@ static size_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val, | |||
111 | } | 111 | } |
112 | 112 | ||
113 | static struct ceph_vxattr_cb ceph_file_vxattrs[] = { | 113 | static struct ceph_vxattr_cb ceph_file_vxattrs[] = { |
114 | { true, "ceph.file.layout", ceph_vxattrcb_layout}, | ||
115 | /* The following extended attribute name is deprecated */ | ||
114 | { true, "ceph.layout", ceph_vxattrcb_layout}, | 116 | { true, "ceph.layout", ceph_vxattrcb_layout}, |
115 | { NULL, NULL } | 117 | { true, NULL, NULL } |
116 | }; | 118 | }; |
117 | 119 | ||
118 | static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode) | 120 | static struct ceph_vxattr_cb *ceph_inode_vxattrs(struct inode *inode) |
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0554b00a7b33..2b243af70aa3 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
@@ -139,7 +139,7 @@ config CIFS_DFS_UPCALL | |||
139 | points. If unsure, say N. | 139 | points. If unsure, say N. |
140 | 140 | ||
141 | config CIFS_FSCACHE | 141 | config CIFS_FSCACHE |
142 | bool "Provide CIFS client caching support (EXPERIMENTAL)" | 142 | bool "Provide CIFS client caching support" |
143 | depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y | 143 | depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y |
144 | help | 144 | help |
145 | Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data | 145 | Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data |
@@ -147,7 +147,7 @@ config CIFS_FSCACHE | |||
147 | manager. If unsure, say N. | 147 | manager. If unsure, say N. |
148 | 148 | ||
149 | config CIFS_ACL | 149 | config CIFS_ACL |
150 | bool "Provide CIFS ACL support (EXPERIMENTAL)" | 150 | bool "Provide CIFS ACL support" |
151 | depends on CIFS_XATTR && KEYS | 151 | depends on CIFS_XATTR && KEYS |
152 | help | 152 | help |
153 | Allows to fetch CIFS/NTFS ACL from the server. The DACL blob | 153 | Allows to fetch CIFS/NTFS ACL from the server. The DACL blob |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 986709a8d903..602f77c304c9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -773,10 +773,11 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) | |||
773 | cifs_dump_mem("Bad SMB: ", buf, | 773 | cifs_dump_mem("Bad SMB: ", buf, |
774 | min_t(unsigned int, server->total_read, 48)); | 774 | min_t(unsigned int, server->total_read, 48)); |
775 | 775 | ||
776 | if (mid) | 776 | if (!mid) |
777 | handle_mid(mid, server, smb_buffer, length); | 777 | return length; |
778 | 778 | ||
779 | return length; | 779 | handle_mid(mid, server, smb_buffer, length); |
780 | return 0; | ||
780 | } | 781 | } |
781 | 782 | ||
782 | static int | 783 | static int |
@@ -2125,7 +2126,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) | |||
2125 | down_read(&key->sem); | 2126 | down_read(&key->sem); |
2126 | upayload = key->payload.data; | 2127 | upayload = key->payload.data; |
2127 | if (IS_ERR_OR_NULL(upayload)) { | 2128 | if (IS_ERR_OR_NULL(upayload)) { |
2128 | rc = PTR_ERR(key); | 2129 | rc = upayload ? PTR_ERR(upayload) : -EINVAL; |
2129 | goto out_key_put; | 2130 | goto out_key_put; |
2130 | } | 2131 | } |
2131 | 2132 | ||
@@ -2142,14 +2143,14 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) | |||
2142 | 2143 | ||
2143 | len = delim - payload; | 2144 | len = delim - payload; |
2144 | if (len > MAX_USERNAME_SIZE || len <= 0) { | 2145 | if (len > MAX_USERNAME_SIZE || len <= 0) { |
2145 | cFYI(1, "Bad value from username search (len=%ld)", len); | 2146 | cFYI(1, "Bad value from username search (len=%zd)", len); |
2146 | rc = -EINVAL; | 2147 | rc = -EINVAL; |
2147 | goto out_key_put; | 2148 | goto out_key_put; |
2148 | } | 2149 | } |
2149 | 2150 | ||
2150 | vol->username = kstrndup(payload, len, GFP_KERNEL); | 2151 | vol->username = kstrndup(payload, len, GFP_KERNEL); |
2151 | if (!vol->username) { | 2152 | if (!vol->username) { |
2152 | cFYI(1, "Unable to allocate %ld bytes for username", len); | 2153 | cFYI(1, "Unable to allocate %zd bytes for username", len); |
2153 | rc = -ENOMEM; | 2154 | rc = -ENOMEM; |
2154 | goto out_key_put; | 2155 | goto out_key_put; |
2155 | } | 2156 | } |
@@ -2157,7 +2158,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) | |||
2157 | 2158 | ||
2158 | len = key->datalen - (len + 1); | 2159 | len = key->datalen - (len + 1); |
2159 | if (len > MAX_PASSWORD_SIZE || len <= 0) { | 2160 | if (len > MAX_PASSWORD_SIZE || len <= 0) { |
2160 | cFYI(1, "Bad len for password search (len=%ld)", len); | 2161 | cFYI(1, "Bad len for password search (len=%zd)", len); |
2161 | rc = -EINVAL; | 2162 | rc = -EINVAL; |
2162 | kfree(vol->username); | 2163 | kfree(vol->username); |
2163 | vol->username = NULL; | 2164 | vol->username = NULL; |
@@ -2167,7 +2168,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) | |||
2167 | ++delim; | 2168 | ++delim; |
2168 | vol->password = kstrndup(delim, len, GFP_KERNEL); | 2169 | vol->password = kstrndup(delim, len, GFP_KERNEL); |
2169 | if (!vol->password) { | 2170 | if (!vol->password) { |
2170 | cFYI(1, "Unable to allocate %ld bytes for password", len); | 2171 | cFYI(1, "Unable to allocate %zd bytes for password", len); |
2171 | rc = -ENOMEM; | 2172 | rc = -ENOMEM; |
2172 | kfree(vol->username); | 2173 | kfree(vol->username); |
2173 | vol->username = NULL; | 2174 | vol->username = NULL; |
@@ -3857,10 +3858,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) | |||
3857 | struct smb_vol *vol_info; | 3858 | struct smb_vol *vol_info; |
3858 | 3859 | ||
3859 | vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); | 3860 | vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); |
3860 | if (vol_info == NULL) { | 3861 | if (vol_info == NULL) |
3861 | tcon = ERR_PTR(-ENOMEM); | 3862 | return ERR_PTR(-ENOMEM); |
3862 | goto out; | ||
3863 | } | ||
3864 | 3863 | ||
3865 | vol_info->local_nls = cifs_sb->local_nls; | 3864 | vol_info->local_nls = cifs_sb->local_nls; |
3866 | vol_info->linux_uid = fsuid; | 3865 | vol_info->linux_uid = fsuid; |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index df8fecb5b993..63a196b97d50 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
@@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, | |||
492 | { | 492 | { |
493 | int xid; | 493 | int xid; |
494 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ | 494 | int rc = 0; /* to get around spurious gcc warning, set to zero here */ |
495 | __u32 oplock = 0; | 495 | __u32 oplock = enable_oplocks ? REQ_OPLOCK : 0; |
496 | __u16 fileHandle = 0; | 496 | __u16 fileHandle = 0; |
497 | bool posix_open = false; | 497 | bool posix_open = false; |
498 | struct cifs_sb_info *cifs_sb; | 498 | struct cifs_sb_info *cifs_sb; |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index d85efad5765f..551d0c2b9736 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
@@ -246,16 +246,15 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, | |||
246 | /* copy user */ | 246 | /* copy user */ |
247 | /* BB what about null user mounts - check that we do this BB */ | 247 | /* BB what about null user mounts - check that we do this BB */ |
248 | /* copy user */ | 248 | /* copy user */ |
249 | if (ses->user_name != NULL) | 249 | if (ses->user_name != NULL) { |
250 | strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE); | 250 | strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE); |
251 | bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE); | ||
252 | } | ||
251 | /* else null user mount */ | 253 | /* else null user mount */ |
252 | |||
253 | bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE); | ||
254 | *bcc_ptr = 0; | 254 | *bcc_ptr = 0; |
255 | bcc_ptr++; /* account for null termination */ | 255 | bcc_ptr++; /* account for null termination */ |
256 | 256 | ||
257 | /* copy domain */ | 257 | /* copy domain */ |
258 | |||
259 | if (ses->domainName != NULL) { | 258 | if (ses->domainName != NULL) { |
260 | strncpy(bcc_ptr, ses->domainName, 256); | 259 | strncpy(bcc_ptr, ses->domainName, 256); |
261 | bcc_ptr += strnlen(ses->domainName, 256); | 260 | bcc_ptr += strnlen(ses->domainName, 256); |
@@ -395,6 +394,10 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, | |||
395 | ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags); | 394 | ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags); |
396 | tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); | 395 | tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); |
397 | tilen = le16_to_cpu(pblob->TargetInfoArray.Length); | 396 | tilen = le16_to_cpu(pblob->TargetInfoArray.Length); |
397 | if (tioffset > blob_len || tioffset + tilen > blob_len) { | ||
398 | cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen); | ||
399 | return -EINVAL; | ||
400 | } | ||
398 | if (tilen) { | 401 | if (tilen) { |
399 | ses->auth_key.response = kmalloc(tilen, GFP_KERNEL); | 402 | ses->auth_key.response = kmalloc(tilen, GFP_KERNEL); |
400 | if (!ses->auth_key.response) { | 403 | if (!ses->auth_key.response) { |
diff --git a/fs/ecryptfs/crypto.c b/fs/ecryptfs/crypto.c index 63ab24510649..ea9931281557 100644 --- a/fs/ecryptfs/crypto.c +++ b/fs/ecryptfs/crypto.c | |||
@@ -1990,6 +1990,17 @@ out: | |||
1990 | return; | 1990 | return; |
1991 | } | 1991 | } |
1992 | 1992 | ||
1993 | static size_t ecryptfs_max_decoded_size(size_t encoded_size) | ||
1994 | { | ||
1995 | /* Not exact; conservatively long. Every block of 4 | ||
1996 | * encoded characters decodes into a block of 3 | ||
1997 | * decoded characters. This segment of code provides | ||
1998 | * the caller with the maximum amount of allocated | ||
1999 | * space that @dst will need to point to in a | ||
2000 | * subsequent call. */ | ||
2001 | return ((encoded_size + 1) * 3) / 4; | ||
2002 | } | ||
2003 | |||
1993 | /** | 2004 | /** |
1994 | * ecryptfs_decode_from_filename | 2005 | * ecryptfs_decode_from_filename |
1995 | * @dst: If NULL, this function only sets @dst_size and returns. If | 2006 | * @dst: If NULL, this function only sets @dst_size and returns. If |
@@ -2008,13 +2019,7 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, | |||
2008 | size_t dst_byte_offset = 0; | 2019 | size_t dst_byte_offset = 0; |
2009 | 2020 | ||
2010 | if (dst == NULL) { | 2021 | if (dst == NULL) { |
2011 | /* Not exact; conservatively long. Every block of 4 | 2022 | (*dst_size) = ecryptfs_max_decoded_size(src_size); |
2012 | * encoded characters decodes into a block of 3 | ||
2013 | * decoded characters. This segment of code provides | ||
2014 | * the caller with the maximum amount of allocated | ||
2015 | * space that @dst will need to point to in a | ||
2016 | * subsequent call. */ | ||
2017 | (*dst_size) = (((src_size + 1) * 3) / 4); | ||
2018 | goto out; | 2023 | goto out; |
2019 | } | 2024 | } |
2020 | while (src_byte_offset < src_size) { | 2025 | while (src_byte_offset < src_size) { |
@@ -2239,3 +2244,52 @@ out_free: | |||
2239 | out: | 2244 | out: |
2240 | return rc; | 2245 | return rc; |
2241 | } | 2246 | } |
2247 | |||
2248 | #define ENC_NAME_MAX_BLOCKLEN_8_OR_16 143 | ||
2249 | |||
2250 | int ecryptfs_set_f_namelen(long *namelen, long lower_namelen, | ||
2251 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat) | ||
2252 | { | ||
2253 | struct blkcipher_desc desc; | ||
2254 | struct mutex *tfm_mutex; | ||
2255 | size_t cipher_blocksize; | ||
2256 | int rc; | ||
2257 | |||
2258 | if (!(mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) { | ||
2259 | (*namelen) = lower_namelen; | ||
2260 | return 0; | ||
2261 | } | ||
2262 | |||
2263 | rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex, | ||
2264 | mount_crypt_stat->global_default_fn_cipher_name); | ||
2265 | if (unlikely(rc)) { | ||
2266 | (*namelen) = 0; | ||
2267 | return rc; | ||
2268 | } | ||
2269 | |||
2270 | mutex_lock(tfm_mutex); | ||
2271 | cipher_blocksize = crypto_blkcipher_blocksize(desc.tfm); | ||
2272 | mutex_unlock(tfm_mutex); | ||
2273 | |||
2274 | /* Return an exact amount for the common cases */ | ||
2275 | if (lower_namelen == NAME_MAX | ||
2276 | && (cipher_blocksize == 8 || cipher_blocksize == 16)) { | ||
2277 | (*namelen) = ENC_NAME_MAX_BLOCKLEN_8_OR_16; | ||
2278 | return 0; | ||
2279 | } | ||
2280 | |||
2281 | /* Return a safe estimate for the uncommon cases */ | ||
2282 | (*namelen) = lower_namelen; | ||
2283 | (*namelen) -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; | ||
2284 | /* Since this is the max decoded size, subtract 1 "decoded block" len */ | ||
2285 | (*namelen) = ecryptfs_max_decoded_size(*namelen) - 3; | ||
2286 | (*namelen) -= ECRYPTFS_TAG_70_MAX_METADATA_SIZE; | ||
2287 | (*namelen) -= ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES; | ||
2288 | /* Worst case is that the filename is padded nearly a full block size */ | ||
2289 | (*namelen) -= cipher_blocksize - 1; | ||
2290 | |||
2291 | if ((*namelen) < 0) | ||
2292 | (*namelen) = 0; | ||
2293 | |||
2294 | return 0; | ||
2295 | } | ||
diff --git a/fs/ecryptfs/ecryptfs_kernel.h b/fs/ecryptfs/ecryptfs_kernel.h index a2362df58ae8..867b64c5d84f 100644 --- a/fs/ecryptfs/ecryptfs_kernel.h +++ b/fs/ecryptfs/ecryptfs_kernel.h | |||
@@ -162,6 +162,10 @@ ecryptfs_get_key_payload_data(struct key *key) | |||
162 | #define ECRYPTFS_NON_NULL 0x42 /* A reasonable substitute for NULL */ | 162 | #define ECRYPTFS_NON_NULL 0x42 /* A reasonable substitute for NULL */ |
163 | #define MD5_DIGEST_SIZE 16 | 163 | #define MD5_DIGEST_SIZE 16 |
164 | #define ECRYPTFS_TAG_70_DIGEST_SIZE MD5_DIGEST_SIZE | 164 | #define ECRYPTFS_TAG_70_DIGEST_SIZE MD5_DIGEST_SIZE |
165 | #define ECRYPTFS_TAG_70_MIN_METADATA_SIZE (1 + ECRYPTFS_MIN_PKT_LEN_SIZE \ | ||
166 | + ECRYPTFS_SIG_SIZE + 1 + 1) | ||
167 | #define ECRYPTFS_TAG_70_MAX_METADATA_SIZE (1 + ECRYPTFS_MAX_PKT_LEN_SIZE \ | ||
168 | + ECRYPTFS_SIG_SIZE + 1 + 1) | ||
165 | #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FEK_ENCRYPTED." | 169 | #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FEK_ENCRYPTED." |
166 | #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 23 | 170 | #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 23 |
167 | #define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED." | 171 | #define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED." |
@@ -701,6 +705,8 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, | |||
701 | size_t *packet_size, | 705 | size_t *packet_size, |
702 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, | 706 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat, |
703 | char *data, size_t max_packet_size); | 707 | char *data, size_t max_packet_size); |
708 | int ecryptfs_set_f_namelen(long *namelen, long lower_namelen, | ||
709 | struct ecryptfs_mount_crypt_stat *mount_crypt_stat); | ||
704 | int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat, | 710 | int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat, |
705 | loff_t offset); | 711 | loff_t offset); |
706 | 712 | ||
diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 19892d7d2ed1..ab35b113003b 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c | |||
@@ -1085,6 +1085,8 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, | |||
1085 | } | 1085 | } |
1086 | 1086 | ||
1087 | rc = vfs_setxattr(lower_dentry, name, value, size, flags); | 1087 | rc = vfs_setxattr(lower_dentry, name, value, size, flags); |
1088 | if (!rc) | ||
1089 | fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode); | ||
1088 | out: | 1090 | out: |
1089 | return rc; | 1091 | return rc; |
1090 | } | 1092 | } |
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c index 8e3b943e330f..2333203a120b 100644 --- a/fs/ecryptfs/keystore.c +++ b/fs/ecryptfs/keystore.c | |||
@@ -679,10 +679,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, | |||
679 | * Octets N3-N4: Block-aligned encrypted filename | 679 | * Octets N3-N4: Block-aligned encrypted filename |
680 | * - Consists of a minimum number of random characters, a \0 | 680 | * - Consists of a minimum number of random characters, a \0 |
681 | * separator, and then the filename */ | 681 | * separator, and then the filename */ |
682 | s->max_packet_size = (1 /* Tag 70 identifier */ | 682 | s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE |
683 | + 3 /* Max Tag 70 packet size */ | ||
684 | + ECRYPTFS_SIG_SIZE /* FNEK sig */ | ||
685 | + 1 /* Cipher identifier */ | ||
686 | + s->block_aligned_filename_size); | 683 | + s->block_aligned_filename_size); |
687 | if (dest == NULL) { | 684 | if (dest == NULL) { |
688 | (*packet_size) = s->max_packet_size; | 685 | (*packet_size) = s->max_packet_size; |
@@ -934,10 +931,10 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, | |||
934 | goto out; | 931 | goto out; |
935 | } | 932 | } |
936 | s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; | 933 | s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; |
937 | if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) { | 934 | if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) { |
938 | printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be " | 935 | printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be " |
939 | "at least [%d]\n", __func__, max_packet_size, | 936 | "at least [%d]\n", __func__, max_packet_size, |
940 | (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)); | 937 | ECRYPTFS_TAG_70_MIN_METADATA_SIZE); |
941 | rc = -EINVAL; | 938 | rc = -EINVAL; |
942 | goto out; | 939 | goto out; |
943 | } | 940 | } |
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 10ec695ccd68..a46b3a8fee1e 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c | |||
@@ -150,7 +150,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, | |||
150 | /* This is a header extent */ | 150 | /* This is a header extent */ |
151 | char *page_virt; | 151 | char *page_virt; |
152 | 152 | ||
153 | page_virt = kmap_atomic(page, KM_USER0); | 153 | page_virt = kmap_atomic(page); |
154 | memset(page_virt, 0, PAGE_CACHE_SIZE); | 154 | memset(page_virt, 0, PAGE_CACHE_SIZE); |
155 | /* TODO: Support more than one header extent */ | 155 | /* TODO: Support more than one header extent */ |
156 | if (view_extent_num == 0) { | 156 | if (view_extent_num == 0) { |
@@ -163,7 +163,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, | |||
163 | crypt_stat, | 163 | crypt_stat, |
164 | &written); | 164 | &written); |
165 | } | 165 | } |
166 | kunmap_atomic(page_virt, KM_USER0); | 166 | kunmap_atomic(page_virt); |
167 | flush_dcache_page(page); | 167 | flush_dcache_page(page); |
168 | if (rc) { | 168 | if (rc) { |
169 | printk(KERN_ERR "%s: Error reading xattr " | 169 | printk(KERN_ERR "%s: Error reading xattr " |
diff --git a/fs/ecryptfs/read_write.c b/fs/ecryptfs/read_write.c index 5c0106f75775..b2a34a192f4f 100644 --- a/fs/ecryptfs/read_write.c +++ b/fs/ecryptfs/read_write.c | |||
@@ -156,7 +156,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
156 | ecryptfs_page_idx, rc); | 156 | ecryptfs_page_idx, rc); |
157 | goto out; | 157 | goto out; |
158 | } | 158 | } |
159 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); | 159 | ecryptfs_page_virt = kmap_atomic(ecryptfs_page); |
160 | 160 | ||
161 | /* | 161 | /* |
162 | * pos: where we're now writing, offset: where the request was | 162 | * pos: where we're now writing, offset: where the request was |
@@ -179,7 +179,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, | |||
179 | (data + data_offset), num_bytes); | 179 | (data + data_offset), num_bytes); |
180 | data_offset += num_bytes; | 180 | data_offset += num_bytes; |
181 | } | 181 | } |
182 | kunmap_atomic(ecryptfs_page_virt, KM_USER0); | 182 | kunmap_atomic(ecryptfs_page_virt); |
183 | flush_dcache_page(ecryptfs_page); | 183 | flush_dcache_page(ecryptfs_page); |
184 | SetPageUptodate(ecryptfs_page); | 184 | SetPageUptodate(ecryptfs_page); |
185 | unlock_page(ecryptfs_page); | 185 | unlock_page(ecryptfs_page); |
diff --git a/fs/ecryptfs/super.c b/fs/ecryptfs/super.c index 9df7fd6e0c39..cf152823bbf4 100644 --- a/fs/ecryptfs/super.c +++ b/fs/ecryptfs/super.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <linux/seq_file.h> | 30 | #include <linux/seq_file.h> |
31 | #include <linux/file.h> | 31 | #include <linux/file.h> |
32 | #include <linux/crypto.h> | 32 | #include <linux/crypto.h> |
33 | #include <linux/statfs.h> | ||
34 | #include <linux/magic.h> | ||
33 | #include "ecryptfs_kernel.h" | 35 | #include "ecryptfs_kernel.h" |
34 | 36 | ||
35 | struct kmem_cache *ecryptfs_inode_info_cache; | 37 | struct kmem_cache *ecryptfs_inode_info_cache; |
@@ -102,10 +104,20 @@ static void ecryptfs_destroy_inode(struct inode *inode) | |||
102 | static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 104 | static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
103 | { | 105 | { |
104 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); | 106 | struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); |
107 | int rc; | ||
105 | 108 | ||
106 | if (!lower_dentry->d_sb->s_op->statfs) | 109 | if (!lower_dentry->d_sb->s_op->statfs) |
107 | return -ENOSYS; | 110 | return -ENOSYS; |
108 | return lower_dentry->d_sb->s_op->statfs(lower_dentry, buf); | 111 | |
112 | rc = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf); | ||
113 | if (rc) | ||
114 | return rc; | ||
115 | |||
116 | buf->f_type = ECRYPTFS_SUPER_MAGIC; | ||
117 | rc = ecryptfs_set_f_namelen(&buf->f_namelen, buf->f_namelen, | ||
118 | &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat); | ||
119 | |||
120 | return rc; | ||
109 | } | 121 | } |
110 | 122 | ||
111 | /** | 123 | /** |
@@ -1071,6 +1071,21 @@ void set_task_comm(struct task_struct *tsk, char *buf) | |||
1071 | perf_event_comm(tsk); | 1071 | perf_event_comm(tsk); |
1072 | } | 1072 | } |
1073 | 1073 | ||
1074 | static void filename_to_taskname(char *tcomm, const char *fn, unsigned int len) | ||
1075 | { | ||
1076 | int i, ch; | ||
1077 | |||
1078 | /* Copies the binary name from after last slash */ | ||
1079 | for (i = 0; (ch = *(fn++)) != '\0';) { | ||
1080 | if (ch == '/') | ||
1081 | i = 0; /* overwrite what we wrote */ | ||
1082 | else | ||
1083 | if (i < len - 1) | ||
1084 | tcomm[i++] = ch; | ||
1085 | } | ||
1086 | tcomm[i] = '\0'; | ||
1087 | } | ||
1088 | |||
1074 | int flush_old_exec(struct linux_binprm * bprm) | 1089 | int flush_old_exec(struct linux_binprm * bprm) |
1075 | { | 1090 | { |
1076 | int retval; | 1091 | int retval; |
@@ -1085,6 +1100,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
1085 | 1100 | ||
1086 | set_mm_exe_file(bprm->mm, bprm->file); | 1101 | set_mm_exe_file(bprm->mm, bprm->file); |
1087 | 1102 | ||
1103 | filename_to_taskname(bprm->tcomm, bprm->filename, sizeof(bprm->tcomm)); | ||
1088 | /* | 1104 | /* |
1089 | * Release all of the old mmap stuff | 1105 | * Release all of the old mmap stuff |
1090 | */ | 1106 | */ |
@@ -1116,10 +1132,6 @@ EXPORT_SYMBOL(would_dump); | |||
1116 | 1132 | ||
1117 | void setup_new_exec(struct linux_binprm * bprm) | 1133 | void setup_new_exec(struct linux_binprm * bprm) |
1118 | { | 1134 | { |
1119 | int i, ch; | ||
1120 | const char *name; | ||
1121 | char tcomm[sizeof(current->comm)]; | ||
1122 | |||
1123 | arch_pick_mmap_layout(current->mm); | 1135 | arch_pick_mmap_layout(current->mm); |
1124 | 1136 | ||
1125 | /* This is the point of no return */ | 1137 | /* This is the point of no return */ |
@@ -1130,18 +1142,7 @@ void setup_new_exec(struct linux_binprm * bprm) | |||
1130 | else | 1142 | else |
1131 | set_dumpable(current->mm, suid_dumpable); | 1143 | set_dumpable(current->mm, suid_dumpable); |
1132 | 1144 | ||
1133 | name = bprm->filename; | 1145 | set_task_comm(current, bprm->tcomm); |
1134 | |||
1135 | /* Copies the binary name from after last slash */ | ||
1136 | for (i=0; (ch = *(name++)) != '\0';) { | ||
1137 | if (ch == '/') | ||
1138 | i = 0; /* overwrite what we wrote */ | ||
1139 | else | ||
1140 | if (i < (sizeof(tcomm) - 1)) | ||
1141 | tcomm[i++] = ch; | ||
1142 | } | ||
1143 | tcomm[i] = '\0'; | ||
1144 | set_task_comm(current, tcomm); | ||
1145 | 1146 | ||
1146 | /* Set the new mm task size. We have to do that late because it may | 1147 | /* Set the new mm task size. We have to do that late because it may |
1147 | * depend on TIF_32BIT which is only updated in flush_thread() on | 1148 | * depend on TIF_32BIT which is only updated in flush_thread() on |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index f855916657ba..5b4a9362d5aa 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -53,14 +53,6 @@ struct wb_writeback_work { | |||
53 | }; | 53 | }; |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * Include the creation of the trace points after defining the | ||
57 | * wb_writeback_work structure so that the definition remains local to this | ||
58 | * file. | ||
59 | */ | ||
60 | #define CREATE_TRACE_POINTS | ||
61 | #include <trace/events/writeback.h> | ||
62 | |||
63 | /* | ||
64 | * We don't actually have pdflush, but this one is exported though /proc... | 56 | * We don't actually have pdflush, but this one is exported though /proc... |
65 | */ | 57 | */ |
66 | int nr_pdflush_threads; | 58 | int nr_pdflush_threads; |
@@ -92,6 +84,14 @@ static inline struct inode *wb_inode(struct list_head *head) | |||
92 | return list_entry(head, struct inode, i_wb_list); | 84 | return list_entry(head, struct inode, i_wb_list); |
93 | } | 85 | } |
94 | 86 | ||
87 | /* | ||
88 | * Include the creation of the trace points after defining the | ||
89 | * wb_writeback_work structure and inline functions so that the definition | ||
90 | * remains local to this file. | ||
91 | */ | ||
92 | #define CREATE_TRACE_POINTS | ||
93 | #include <trace/events/writeback.h> | ||
94 | |||
95 | /* Wakeup flusher thread or forker thread to fork it. Requires bdi->wb_lock. */ | 95 | /* Wakeup flusher thread or forker thread to fork it. Requires bdi->wb_lock. */ |
96 | static void bdi_wakeup_flusher(struct backing_dev_info *bdi) | 96 | static void bdi_wakeup_flusher(struct backing_dev_info *bdi) |
97 | { | 97 | { |
diff --git a/fs/ioprio.c b/fs/ioprio.c index f84b380d65e5..0f1b9515213b 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c | |||
@@ -51,7 +51,7 @@ int set_task_ioprio(struct task_struct *task, int ioprio) | |||
51 | ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); | 51 | ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); |
52 | if (ioc) { | 52 | if (ioc) { |
53 | ioc_ioprio_changed(ioc, ioprio); | 53 | ioc_ioprio_changed(ioc, ioprio); |
54 | put_io_context(ioc, NULL); | 54 | put_io_context(ioc); |
55 | } | 55 | } |
56 | 56 | ||
57 | return err; | 57 | return err; |
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a01cdad6aad1..eafb8d37a6fb 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c | |||
@@ -335,7 +335,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl | |||
335 | void *ebuf; | 335 | void *ebuf; |
336 | uint32_t ofs; | 336 | uint32_t ofs; |
337 | size_t retlen; | 337 | size_t retlen; |
338 | int ret = -EIO; | 338 | int ret; |
339 | unsigned long *wordebuf; | 339 | unsigned long *wordebuf; |
340 | 340 | ||
341 | ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen, | 341 | ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen, |
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c index e97404d611e0..9c501449450d 100644 --- a/fs/logfs/dev_mtd.c +++ b/fs/logfs/dev_mtd.c | |||
@@ -152,9 +152,6 @@ static struct page *logfs_mtd_find_first_sb(struct super_block *sb, u64 *ofs) | |||
152 | filler_t *filler = logfs_mtd_readpage; | 152 | filler_t *filler = logfs_mtd_readpage; |
153 | struct mtd_info *mtd = super->s_mtd; | 153 | struct mtd_info *mtd = super->s_mtd; |
154 | 154 | ||
155 | if (!mtd_can_have_bb(mtd)) | ||
156 | return NULL; | ||
157 | |||
158 | *ofs = 0; | 155 | *ofs = 0; |
159 | while (mtd_block_isbad(mtd, *ofs)) { | 156 | while (mtd_block_isbad(mtd, *ofs)) { |
160 | *ofs += mtd->erasesize; | 157 | *ofs += mtd->erasesize; |
@@ -172,9 +169,6 @@ static struct page *logfs_mtd_find_last_sb(struct super_block *sb, u64 *ofs) | |||
172 | filler_t *filler = logfs_mtd_readpage; | 169 | filler_t *filler = logfs_mtd_readpage; |
173 | struct mtd_info *mtd = super->s_mtd; | 170 | struct mtd_info *mtd = super->s_mtd; |
174 | 171 | ||
175 | if (!mtd_can_have_bb(mtd)) | ||
176 | return NULL; | ||
177 | |||
178 | *ofs = mtd->size - mtd->erasesize; | 172 | *ofs = mtd->size - mtd->erasesize; |
179 | while (mtd_block_isbad(mtd, *ofs)) { | 173 | while (mtd_block_isbad(mtd, *ofs)) { |
180 | *ofs -= mtd->erasesize; | 174 | *ofs -= mtd->erasesize; |
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 886649627c3d..2a70fce70c65 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
@@ -603,6 +603,8 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, | |||
603 | nsegs = argv[4].v_nmembs; | 603 | nsegs = argv[4].v_nmembs; |
604 | if (argv[4].v_size != argsz[4]) | 604 | if (argv[4].v_size != argsz[4]) |
605 | goto out; | 605 | goto out; |
606 | if (nsegs > UINT_MAX / sizeof(__u64)) | ||
607 | goto out; | ||
606 | 608 | ||
607 | /* | 609 | /* |
608 | * argv[4] points to segment numbers this ioctl cleans. We | 610 | * argv[4] points to segment numbers this ioctl cleans. We |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 9cde9edf9c4d..d4548dd49b02 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -198,26 +198,6 @@ static int proc_root_link(struct dentry *dentry, struct path *path) | |||
198 | return result; | 198 | return result; |
199 | } | 199 | } |
200 | 200 | ||
201 | static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode) | ||
202 | { | ||
203 | struct mm_struct *mm; | ||
204 | int err; | ||
205 | |||
206 | err = mutex_lock_killable(&task->signal->cred_guard_mutex); | ||
207 | if (err) | ||
208 | return ERR_PTR(err); | ||
209 | |||
210 | mm = get_task_mm(task); | ||
211 | if (mm && mm != current->mm && | ||
212 | !ptrace_may_access(task, mode)) { | ||
213 | mmput(mm); | ||
214 | mm = ERR_PTR(-EACCES); | ||
215 | } | ||
216 | mutex_unlock(&task->signal->cred_guard_mutex); | ||
217 | |||
218 | return mm; | ||
219 | } | ||
220 | |||
221 | struct mm_struct *mm_for_maps(struct task_struct *task) | 201 | struct mm_struct *mm_for_maps(struct task_struct *task) |
222 | { | 202 | { |
223 | return mm_access(task, PTRACE_MODE_READ); | 203 | return mm_access(task, PTRACE_MODE_READ); |
@@ -711,6 +691,13 @@ static int mem_open(struct inode* inode, struct file* file) | |||
711 | if (IS_ERR(mm)) | 691 | if (IS_ERR(mm)) |
712 | return PTR_ERR(mm); | 692 | return PTR_ERR(mm); |
713 | 693 | ||
694 | if (mm) { | ||
695 | /* ensure this mm_struct can't be freed */ | ||
696 | atomic_inc(&mm->mm_count); | ||
697 | /* but do not pin its memory */ | ||
698 | mmput(mm); | ||
699 | } | ||
700 | |||
714 | /* OK to pass negative loff_t, we can catch out-of-range */ | 701 | /* OK to pass negative loff_t, we can catch out-of-range */ |
715 | file->f_mode |= FMODE_UNSIGNED_OFFSET; | 702 | file->f_mode |= FMODE_UNSIGNED_OFFSET; |
716 | file->private_data = mm; | 703 | file->private_data = mm; |
@@ -718,57 +705,13 @@ static int mem_open(struct inode* inode, struct file* file) | |||
718 | return 0; | 705 | return 0; |
719 | } | 706 | } |
720 | 707 | ||
721 | static ssize_t mem_read(struct file * file, char __user * buf, | 708 | static ssize_t mem_rw(struct file *file, char __user *buf, |
722 | size_t count, loff_t *ppos) | 709 | size_t count, loff_t *ppos, int write) |
723 | { | 710 | { |
724 | int ret; | ||
725 | char *page; | ||
726 | unsigned long src = *ppos; | ||
727 | struct mm_struct *mm = file->private_data; | 711 | struct mm_struct *mm = file->private_data; |
728 | 712 | unsigned long addr = *ppos; | |
729 | if (!mm) | 713 | ssize_t copied; |
730 | return 0; | ||
731 | |||
732 | page = (char *)__get_free_page(GFP_TEMPORARY); | ||
733 | if (!page) | ||
734 | return -ENOMEM; | ||
735 | |||
736 | ret = 0; | ||
737 | |||
738 | while (count > 0) { | ||
739 | int this_len, retval; | ||
740 | |||
741 | this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; | ||
742 | retval = access_remote_vm(mm, src, page, this_len, 0); | ||
743 | if (!retval) { | ||
744 | if (!ret) | ||
745 | ret = -EIO; | ||
746 | break; | ||
747 | } | ||
748 | |||
749 | if (copy_to_user(buf, page, retval)) { | ||
750 | ret = -EFAULT; | ||
751 | break; | ||
752 | } | ||
753 | |||
754 | ret += retval; | ||
755 | src += retval; | ||
756 | buf += retval; | ||
757 | count -= retval; | ||
758 | } | ||
759 | *ppos = src; | ||
760 | |||
761 | free_page((unsigned long) page); | ||
762 | return ret; | ||
763 | } | ||
764 | |||
765 | static ssize_t mem_write(struct file * file, const char __user *buf, | ||
766 | size_t count, loff_t *ppos) | ||
767 | { | ||
768 | int copied; | ||
769 | char *page; | 714 | char *page; |
770 | unsigned long dst = *ppos; | ||
771 | struct mm_struct *mm = file->private_data; | ||
772 | 715 | ||
773 | if (!mm) | 716 | if (!mm) |
774 | return 0; | 717 | return 0; |
@@ -778,31 +721,54 @@ static ssize_t mem_write(struct file * file, const char __user *buf, | |||
778 | return -ENOMEM; | 721 | return -ENOMEM; |
779 | 722 | ||
780 | copied = 0; | 723 | copied = 0; |
724 | if (!atomic_inc_not_zero(&mm->mm_users)) | ||
725 | goto free; | ||
726 | |||
781 | while (count > 0) { | 727 | while (count > 0) { |
782 | int this_len, retval; | 728 | int this_len = min_t(int, count, PAGE_SIZE); |
783 | 729 | ||
784 | this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count; | 730 | if (write && copy_from_user(page, buf, this_len)) { |
785 | if (copy_from_user(page, buf, this_len)) { | ||
786 | copied = -EFAULT; | 731 | copied = -EFAULT; |
787 | break; | 732 | break; |
788 | } | 733 | } |
789 | retval = access_remote_vm(mm, dst, page, this_len, 1); | 734 | |
790 | if (!retval) { | 735 | this_len = access_remote_vm(mm, addr, page, this_len, write); |
736 | if (!this_len) { | ||
791 | if (!copied) | 737 | if (!copied) |
792 | copied = -EIO; | 738 | copied = -EIO; |
793 | break; | 739 | break; |
794 | } | 740 | } |
795 | copied += retval; | 741 | |
796 | buf += retval; | 742 | if (!write && copy_to_user(buf, page, this_len)) { |
797 | dst += retval; | 743 | copied = -EFAULT; |
798 | count -= retval; | 744 | break; |
745 | } | ||
746 | |||
747 | buf += this_len; | ||
748 | addr += this_len; | ||
749 | copied += this_len; | ||
750 | count -= this_len; | ||
799 | } | 751 | } |
800 | *ppos = dst; | 752 | *ppos = addr; |
801 | 753 | ||
754 | mmput(mm); | ||
755 | free: | ||
802 | free_page((unsigned long) page); | 756 | free_page((unsigned long) page); |
803 | return copied; | 757 | return copied; |
804 | } | 758 | } |
805 | 759 | ||
760 | static ssize_t mem_read(struct file *file, char __user *buf, | ||
761 | size_t count, loff_t *ppos) | ||
762 | { | ||
763 | return mem_rw(file, buf, count, ppos, 0); | ||
764 | } | ||
765 | |||
766 | static ssize_t mem_write(struct file *file, const char __user *buf, | ||
767 | size_t count, loff_t *ppos) | ||
768 | { | ||
769 | return mem_rw(file, (char __user*)buf, count, ppos, 1); | ||
770 | } | ||
771 | |||
806 | loff_t mem_lseek(struct file *file, loff_t offset, int orig) | 772 | loff_t mem_lseek(struct file *file, loff_t offset, int orig) |
807 | { | 773 | { |
808 | switch (orig) { | 774 | switch (orig) { |
@@ -822,8 +788,8 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig) | |||
822 | static int mem_release(struct inode *inode, struct file *file) | 788 | static int mem_release(struct inode *inode, struct file *file) |
823 | { | 789 | { |
824 | struct mm_struct *mm = file->private_data; | 790 | struct mm_struct *mm = file->private_data; |
825 | 791 | if (mm) | |
826 | mmput(mm); | 792 | mmdrop(mm); |
827 | return 0; | 793 | return 0; |
828 | } | 794 | } |
829 | 795 | ||
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h index 292eff198030..ab7c53fe346e 100644 --- a/fs/xfs/kmem.h +++ b/fs/xfs/kmem.h | |||
@@ -110,10 +110,4 @@ kmem_zone_destroy(kmem_zone_t *zone) | |||
110 | extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast); | 110 | extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast); |
111 | extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast); | 111 | extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast); |
112 | 112 | ||
113 | static inline int | ||
114 | kmem_shake_allow(gfp_t gfp_mask) | ||
115 | { | ||
116 | return ((gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_FS)); | ||
117 | } | ||
118 | |||
119 | #endif /* __XFS_SUPPORT_KMEM_H__ */ | 113 | #endif /* __XFS_SUPPORT_KMEM_H__ */ |
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index b4ff40b5f918..cbcb7bea38e2 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c | |||
@@ -63,82 +63,6 @@ int xfs_dqerror_mod = 33; | |||
63 | static struct lock_class_key xfs_dquot_other_class; | 63 | static struct lock_class_key xfs_dquot_other_class; |
64 | 64 | ||
65 | /* | 65 | /* |
66 | * Allocate and initialize a dquot. We don't always allocate fresh memory; | ||
67 | * we try to reclaim a free dquot if the number of incore dquots are above | ||
68 | * a threshold. | ||
69 | * The only field inside the core that gets initialized at this point | ||
70 | * is the d_id field. The idea is to fill in the entire q_core | ||
71 | * when we read in the on disk dquot. | ||
72 | */ | ||
73 | STATIC xfs_dquot_t * | ||
74 | xfs_qm_dqinit( | ||
75 | xfs_mount_t *mp, | ||
76 | xfs_dqid_t id, | ||
77 | uint type) | ||
78 | { | ||
79 | xfs_dquot_t *dqp; | ||
80 | boolean_t brandnewdquot; | ||
81 | |||
82 | brandnewdquot = xfs_qm_dqalloc_incore(&dqp); | ||
83 | dqp->dq_flags = type; | ||
84 | dqp->q_core.d_id = cpu_to_be32(id); | ||
85 | dqp->q_mount = mp; | ||
86 | |||
87 | /* | ||
88 | * No need to re-initialize these if this is a reclaimed dquot. | ||
89 | */ | ||
90 | if (brandnewdquot) { | ||
91 | INIT_LIST_HEAD(&dqp->q_freelist); | ||
92 | mutex_init(&dqp->q_qlock); | ||
93 | init_waitqueue_head(&dqp->q_pinwait); | ||
94 | |||
95 | /* | ||
96 | * Because we want to use a counting completion, complete | ||
97 | * the flush completion once to allow a single access to | ||
98 | * the flush completion without blocking. | ||
99 | */ | ||
100 | init_completion(&dqp->q_flush); | ||
101 | complete(&dqp->q_flush); | ||
102 | |||
103 | trace_xfs_dqinit(dqp); | ||
104 | } else { | ||
105 | /* | ||
106 | * Only the q_core portion was zeroed in dqreclaim_one(). | ||
107 | * So, we need to reset others. | ||
108 | */ | ||
109 | dqp->q_nrefs = 0; | ||
110 | dqp->q_blkno = 0; | ||
111 | INIT_LIST_HEAD(&dqp->q_mplist); | ||
112 | INIT_LIST_HEAD(&dqp->q_hashlist); | ||
113 | dqp->q_bufoffset = 0; | ||
114 | dqp->q_fileoffset = 0; | ||
115 | dqp->q_transp = NULL; | ||
116 | dqp->q_gdquot = NULL; | ||
117 | dqp->q_res_bcount = 0; | ||
118 | dqp->q_res_icount = 0; | ||
119 | dqp->q_res_rtbcount = 0; | ||
120 | atomic_set(&dqp->q_pincount, 0); | ||
121 | dqp->q_hash = NULL; | ||
122 | ASSERT(list_empty(&dqp->q_freelist)); | ||
123 | |||
124 | trace_xfs_dqreuse(dqp); | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * In either case we need to make sure group quotas have a different | ||
129 | * lock class than user quotas, to make sure lockdep knows we can | ||
130 | * locks of one of each at the same time. | ||
131 | */ | ||
132 | if (!(type & XFS_DQ_USER)) | ||
133 | lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); | ||
134 | |||
135 | /* | ||
136 | * log item gets initialized later | ||
137 | */ | ||
138 | return (dqp); | ||
139 | } | ||
140 | |||
141 | /* | ||
142 | * This is called to free all the memory associated with a dquot | 66 | * This is called to free all the memory associated with a dquot |
143 | */ | 67 | */ |
144 | void | 68 | void |
@@ -567,7 +491,32 @@ xfs_qm_dqread( | |||
567 | int error; | 491 | int error; |
568 | int cancelflags = 0; | 492 | int cancelflags = 0; |
569 | 493 | ||
570 | dqp = xfs_qm_dqinit(mp, id, type); | 494 | |
495 | dqp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP); | ||
496 | |||
497 | dqp->dq_flags = type; | ||
498 | dqp->q_core.d_id = cpu_to_be32(id); | ||
499 | dqp->q_mount = mp; | ||
500 | INIT_LIST_HEAD(&dqp->q_freelist); | ||
501 | mutex_init(&dqp->q_qlock); | ||
502 | init_waitqueue_head(&dqp->q_pinwait); | ||
503 | |||
504 | /* | ||
505 | * Because we want to use a counting completion, complete | ||
506 | * the flush completion once to allow a single access to | ||
507 | * the flush completion without blocking. | ||
508 | */ | ||
509 | init_completion(&dqp->q_flush); | ||
510 | complete(&dqp->q_flush); | ||
511 | |||
512 | /* | ||
513 | * Make sure group quotas have a different lock class than user | ||
514 | * quotas. | ||
515 | */ | ||
516 | if (!(type & XFS_DQ_USER)) | ||
517 | lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); | ||
518 | |||
519 | atomic_inc(&xfs_Gqm->qm_totaldquots); | ||
571 | 520 | ||
572 | trace_xfs_dqread(dqp); | 521 | trace_xfs_dqread(dqp); |
573 | 522 | ||
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 541a508adea1..15ff5392fb65 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -1489,7 +1489,7 @@ xlog_recover_add_to_cont_trans( | |||
1489 | old_ptr = item->ri_buf[item->ri_cnt-1].i_addr; | 1489 | old_ptr = item->ri_buf[item->ri_cnt-1].i_addr; |
1490 | old_len = item->ri_buf[item->ri_cnt-1].i_len; | 1490 | old_len = item->ri_buf[item->ri_cnt-1].i_len; |
1491 | 1491 | ||
1492 | ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0u); | 1492 | ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP); |
1493 | memcpy(&ptr[old_len], dp, len); /* d, s, l */ | 1493 | memcpy(&ptr[old_len], dp, len); /* d, s, l */ |
1494 | item->ri_buf[item->ri_cnt-1].i_len += len; | 1494 | item->ri_buf[item->ri_cnt-1].i_len += len; |
1495 | item->ri_buf[item->ri_cnt-1].i_addr = ptr; | 1495 | item->ri_buf[item->ri_cnt-1].i_addr = ptr; |
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c index 671f37eae1c7..c436def733bf 100644 --- a/fs/xfs/xfs_qm.c +++ b/fs/xfs/xfs_qm.c | |||
@@ -50,7 +50,6 @@ | |||
50 | */ | 50 | */ |
51 | struct mutex xfs_Gqm_lock; | 51 | struct mutex xfs_Gqm_lock; |
52 | struct xfs_qm *xfs_Gqm; | 52 | struct xfs_qm *xfs_Gqm; |
53 | uint ndquot; | ||
54 | 53 | ||
55 | kmem_zone_t *qm_dqzone; | 54 | kmem_zone_t *qm_dqzone; |
56 | kmem_zone_t *qm_dqtrxzone; | 55 | kmem_zone_t *qm_dqtrxzone; |
@@ -93,7 +92,6 @@ xfs_Gqm_init(void) | |||
93 | goto out_free_udqhash; | 92 | goto out_free_udqhash; |
94 | 93 | ||
95 | hsize /= sizeof(xfs_dqhash_t); | 94 | hsize /= sizeof(xfs_dqhash_t); |
96 | ndquot = hsize << 8; | ||
97 | 95 | ||
98 | xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP); | 96 | xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP); |
99 | xqm->qm_dqhashmask = hsize - 1; | 97 | xqm->qm_dqhashmask = hsize - 1; |
@@ -137,7 +135,6 @@ xfs_Gqm_init(void) | |||
137 | xqm->qm_dqtrxzone = qm_dqtrxzone; | 135 | xqm->qm_dqtrxzone = qm_dqtrxzone; |
138 | 136 | ||
139 | atomic_set(&xqm->qm_totaldquots, 0); | 137 | atomic_set(&xqm->qm_totaldquots, 0); |
140 | xqm->qm_dqfree_ratio = XFS_QM_DQFREE_RATIO; | ||
141 | xqm->qm_nrefs = 0; | 138 | xqm->qm_nrefs = 0; |
142 | return xqm; | 139 | return xqm; |
143 | 140 | ||
@@ -1600,216 +1597,150 @@ xfs_qm_init_quotainos( | |||
1600 | return 0; | 1597 | return 0; |
1601 | } | 1598 | } |
1602 | 1599 | ||
1600 | STATIC void | ||
1601 | xfs_qm_dqfree_one( | ||
1602 | struct xfs_dquot *dqp) | ||
1603 | { | ||
1604 | struct xfs_mount *mp = dqp->q_mount; | ||
1605 | struct xfs_quotainfo *qi = mp->m_quotainfo; | ||
1603 | 1606 | ||
1607 | mutex_lock(&dqp->q_hash->qh_lock); | ||
1608 | list_del_init(&dqp->q_hashlist); | ||
1609 | dqp->q_hash->qh_version++; | ||
1610 | mutex_unlock(&dqp->q_hash->qh_lock); | ||
1604 | 1611 | ||
1605 | /* | 1612 | mutex_lock(&qi->qi_dqlist_lock); |
1606 | * Pop the least recently used dquot off the freelist and recycle it. | 1613 | list_del_init(&dqp->q_mplist); |
1607 | */ | 1614 | qi->qi_dquots--; |
1608 | STATIC struct xfs_dquot * | 1615 | qi->qi_dqreclaims++; |
1609 | xfs_qm_dqreclaim_one(void) | 1616 | mutex_unlock(&qi->qi_dqlist_lock); |
1617 | |||
1618 | xfs_qm_dqdestroy(dqp); | ||
1619 | } | ||
1620 | |||
1621 | STATIC void | ||
1622 | xfs_qm_dqreclaim_one( | ||
1623 | struct xfs_dquot *dqp, | ||
1624 | struct list_head *dispose_list) | ||
1610 | { | 1625 | { |
1611 | struct xfs_dquot *dqp; | 1626 | struct xfs_mount *mp = dqp->q_mount; |
1612 | int restarts = 0; | 1627 | int error; |
1613 | 1628 | ||
1614 | mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); | 1629 | if (!xfs_dqlock_nowait(dqp)) |
1615 | restart: | 1630 | goto out_busy; |
1616 | list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) { | ||
1617 | struct xfs_mount *mp = dqp->q_mount; | ||
1618 | 1631 | ||
1619 | if (!xfs_dqlock_nowait(dqp)) | 1632 | /* |
1620 | continue; | 1633 | * This dquot has acquired a reference in the meantime remove it from |
1634 | * the freelist and try again. | ||
1635 | */ | ||
1636 | if (dqp->q_nrefs) { | ||
1637 | xfs_dqunlock(dqp); | ||
1621 | 1638 | ||
1622 | /* | 1639 | trace_xfs_dqreclaim_want(dqp); |
1623 | * This dquot has already been grabbed by dqlookup. | 1640 | XQM_STATS_INC(xqmstats.xs_qm_dqwants); |
1624 | * Remove it from the freelist and try again. | ||
1625 | */ | ||
1626 | if (dqp->q_nrefs) { | ||
1627 | trace_xfs_dqreclaim_want(dqp); | ||
1628 | XQM_STATS_INC(xqmstats.xs_qm_dqwants); | ||
1629 | |||
1630 | list_del_init(&dqp->q_freelist); | ||
1631 | xfs_Gqm->qm_dqfrlist_cnt--; | ||
1632 | restarts++; | ||
1633 | goto dqunlock; | ||
1634 | } | ||
1635 | 1641 | ||
1636 | ASSERT(dqp->q_hash); | 1642 | list_del_init(&dqp->q_freelist); |
1637 | ASSERT(!list_empty(&dqp->q_mplist)); | 1643 | xfs_Gqm->qm_dqfrlist_cnt--; |
1644 | return; | ||
1645 | } | ||
1638 | 1646 | ||
1639 | /* | 1647 | ASSERT(dqp->q_hash); |
1640 | * Try to grab the flush lock. If this dquot is in the process | 1648 | ASSERT(!list_empty(&dqp->q_mplist)); |
1641 | * of getting flushed to disk, we don't want to reclaim it. | ||
1642 | */ | ||
1643 | if (!xfs_dqflock_nowait(dqp)) | ||
1644 | goto dqunlock; | ||
1645 | 1649 | ||
1646 | /* | 1650 | /* |
1647 | * We have the flush lock so we know that this is not in the | 1651 | * Try to grab the flush lock. If this dquot is in the process of |
1648 | * process of being flushed. So, if this is dirty, flush it | 1652 | * getting flushed to disk, we don't want to reclaim it. |
1649 | * DELWRI so that we don't get a freelist infested with | 1653 | */ |
1650 | * dirty dquots. | 1654 | if (!xfs_dqflock_nowait(dqp)) |
1651 | */ | 1655 | goto out_busy; |
1652 | if (XFS_DQ_IS_DIRTY(dqp)) { | ||
1653 | int error; | ||
1654 | 1656 | ||
1655 | trace_xfs_dqreclaim_dirty(dqp); | 1657 | /* |
1658 | * We have the flush lock so we know that this is not in the | ||
1659 | * process of being flushed. So, if this is dirty, flush it | ||
1660 | * DELWRI so that we don't get a freelist infested with | ||
1661 | * dirty dquots. | ||
1662 | */ | ||
1663 | if (XFS_DQ_IS_DIRTY(dqp)) { | ||
1664 | trace_xfs_dqreclaim_dirty(dqp); | ||
1656 | 1665 | ||
1657 | /* | 1666 | /* |
1658 | * We flush it delayed write, so don't bother | 1667 | * We flush it delayed write, so don't bother releasing the |
1659 | * releasing the freelist lock. | 1668 | * freelist lock. |
1660 | */ | 1669 | */ |
1661 | error = xfs_qm_dqflush(dqp, SYNC_TRYLOCK); | 1670 | error = xfs_qm_dqflush(dqp, 0); |
1662 | if (error) { | 1671 | if (error) { |
1663 | xfs_warn(mp, "%s: dquot %p flush failed", | 1672 | xfs_warn(mp, "%s: dquot %p flush failed", |
1664 | __func__, dqp); | 1673 | __func__, dqp); |
1665 | } | ||
1666 | goto dqunlock; | ||
1667 | } | 1674 | } |
1668 | xfs_dqfunlock(dqp); | ||
1669 | 1675 | ||
1670 | /* | 1676 | /* |
1671 | * Prevent lookup now that we are going to reclaim the dquot. | 1677 | * Give the dquot another try on the freelist, as the |
1672 | * Once XFS_DQ_FREEING is set lookup won't touch the dquot, | 1678 | * flushing will take some time. |
1673 | * thus we can drop the lock now. | ||
1674 | */ | 1679 | */ |
1675 | dqp->dq_flags |= XFS_DQ_FREEING; | 1680 | goto out_busy; |
1676 | xfs_dqunlock(dqp); | 1681 | } |
1677 | 1682 | xfs_dqfunlock(dqp); | |
1678 | mutex_lock(&dqp->q_hash->qh_lock); | ||
1679 | list_del_init(&dqp->q_hashlist); | ||
1680 | dqp->q_hash->qh_version++; | ||
1681 | mutex_unlock(&dqp->q_hash->qh_lock); | ||
1682 | |||
1683 | mutex_lock(&mp->m_quotainfo->qi_dqlist_lock); | ||
1684 | list_del_init(&dqp->q_mplist); | ||
1685 | mp->m_quotainfo->qi_dquots--; | ||
1686 | mp->m_quotainfo->qi_dqreclaims++; | ||
1687 | mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); | ||
1688 | 1683 | ||
1689 | ASSERT(dqp->q_nrefs == 0); | 1684 | /* |
1690 | list_del_init(&dqp->q_freelist); | 1685 | * Prevent lookups now that we are past the point of no return. |
1691 | xfs_Gqm->qm_dqfrlist_cnt--; | 1686 | */ |
1687 | dqp->dq_flags |= XFS_DQ_FREEING; | ||
1688 | xfs_dqunlock(dqp); | ||
1692 | 1689 | ||
1693 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | 1690 | ASSERT(dqp->q_nrefs == 0); |
1694 | return dqp; | 1691 | list_move_tail(&dqp->q_freelist, dispose_list); |
1695 | dqunlock: | 1692 | xfs_Gqm->qm_dqfrlist_cnt--; |
1696 | xfs_dqunlock(dqp); | ||
1697 | if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) | ||
1698 | break; | ||
1699 | goto restart; | ||
1700 | } | ||
1701 | 1693 | ||
1702 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | 1694 | trace_xfs_dqreclaim_done(dqp); |
1703 | return NULL; | 1695 | XQM_STATS_INC(xqmstats.xs_qm_dqreclaims); |
1704 | } | 1696 | return; |
1705 | 1697 | ||
1706 | /* | 1698 | out_busy: |
1707 | * Traverse the freelist of dquots and attempt to reclaim a maximum of | 1699 | xfs_dqunlock(dqp); |
1708 | * 'howmany' dquots. This operation races with dqlookup(), and attempts to | ||
1709 | * favor the lookup function ... | ||
1710 | */ | ||
1711 | STATIC int | ||
1712 | xfs_qm_shake_freelist( | ||
1713 | int howmany) | ||
1714 | { | ||
1715 | int nreclaimed = 0; | ||
1716 | xfs_dquot_t *dqp; | ||
1717 | 1700 | ||
1718 | if (howmany <= 0) | 1701 | /* |
1719 | return 0; | 1702 | * Move the dquot to the tail of the list so that we don't spin on it. |
1703 | */ | ||
1704 | list_move_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist); | ||
1720 | 1705 | ||
1721 | while (nreclaimed < howmany) { | 1706 | trace_xfs_dqreclaim_busy(dqp); |
1722 | dqp = xfs_qm_dqreclaim_one(); | 1707 | XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses); |
1723 | if (!dqp) | ||
1724 | return nreclaimed; | ||
1725 | xfs_qm_dqdestroy(dqp); | ||
1726 | nreclaimed++; | ||
1727 | } | ||
1728 | return nreclaimed; | ||
1729 | } | 1708 | } |
1730 | 1709 | ||
1731 | /* | ||
1732 | * The kmem_shake interface is invoked when memory is running low. | ||
1733 | */ | ||
1734 | /* ARGSUSED */ | ||
1735 | STATIC int | 1710 | STATIC int |
1736 | xfs_qm_shake( | 1711 | xfs_qm_shake( |
1737 | struct shrinker *shrink, | 1712 | struct shrinker *shrink, |
1738 | struct shrink_control *sc) | 1713 | struct shrink_control *sc) |
1739 | { | 1714 | { |
1740 | int ndqused, nfree, n; | 1715 | int nr_to_scan = sc->nr_to_scan; |
1741 | gfp_t gfp_mask = sc->gfp_mask; | 1716 | LIST_HEAD (dispose_list); |
1742 | 1717 | struct xfs_dquot *dqp; | |
1743 | if (!kmem_shake_allow(gfp_mask)) | ||
1744 | return 0; | ||
1745 | if (!xfs_Gqm) | ||
1746 | return 0; | ||
1747 | |||
1748 | nfree = xfs_Gqm->qm_dqfrlist_cnt; /* free dquots */ | ||
1749 | /* incore dquots in all f/s's */ | ||
1750 | ndqused = atomic_read(&xfs_Gqm->qm_totaldquots) - nfree; | ||
1751 | |||
1752 | ASSERT(ndqused >= 0); | ||
1753 | 1718 | ||
1754 | if (nfree <= ndqused && nfree < ndquot) | 1719 | if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT)) |
1755 | return 0; | 1720 | return 0; |
1721 | if (!nr_to_scan) | ||
1722 | goto out; | ||
1756 | 1723 | ||
1757 | ndqused *= xfs_Gqm->qm_dqfree_ratio; /* target # of free dquots */ | 1724 | mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); |
1758 | n = nfree - ndqused - ndquot; /* # over target */ | 1725 | while (!list_empty(&xfs_Gqm->qm_dqfrlist)) { |
1759 | 1726 | if (nr_to_scan-- <= 0) | |
1760 | return xfs_qm_shake_freelist(MAX(nfree, n)); | 1727 | break; |
1761 | } | 1728 | dqp = list_first_entry(&xfs_Gqm->qm_dqfrlist, struct xfs_dquot, |
1762 | 1729 | q_freelist); | |
1763 | 1730 | xfs_qm_dqreclaim_one(dqp, &dispose_list); | |
1764 | /*------------------------------------------------------------------*/ | ||
1765 | |||
1766 | /* | ||
1767 | * Return a new incore dquot. Depending on the number of | ||
1768 | * dquots in the system, we either allocate a new one on the kernel heap, | ||
1769 | * or reclaim a free one. | ||
1770 | * Return value is B_TRUE if we allocated a new dquot, B_FALSE if we managed | ||
1771 | * to reclaim an existing one from the freelist. | ||
1772 | */ | ||
1773 | boolean_t | ||
1774 | xfs_qm_dqalloc_incore( | ||
1775 | xfs_dquot_t **O_dqpp) | ||
1776 | { | ||
1777 | xfs_dquot_t *dqp; | ||
1778 | |||
1779 | /* | ||
1780 | * Check against high water mark to see if we want to pop | ||
1781 | * a nincompoop dquot off the freelist. | ||
1782 | */ | ||
1783 | if (atomic_read(&xfs_Gqm->qm_totaldquots) >= ndquot) { | ||
1784 | /* | ||
1785 | * Try to recycle a dquot from the freelist. | ||
1786 | */ | ||
1787 | if ((dqp = xfs_qm_dqreclaim_one())) { | ||
1788 | XQM_STATS_INC(xqmstats.xs_qm_dqreclaims); | ||
1789 | /* | ||
1790 | * Just zero the core here. The rest will get | ||
1791 | * reinitialized by caller. XXX we shouldn't even | ||
1792 | * do this zero ... | ||
1793 | */ | ||
1794 | memset(&dqp->q_core, 0, sizeof(dqp->q_core)); | ||
1795 | *O_dqpp = dqp; | ||
1796 | return B_FALSE; | ||
1797 | } | ||
1798 | XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses); | ||
1799 | } | 1731 | } |
1732 | mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); | ||
1800 | 1733 | ||
1801 | /* | 1734 | while (!list_empty(&dispose_list)) { |
1802 | * Allocate a brand new dquot on the kernel heap and return it | 1735 | dqp = list_first_entry(&dispose_list, struct xfs_dquot, |
1803 | * to the caller to initialize. | 1736 | q_freelist); |
1804 | */ | 1737 | list_del_init(&dqp->q_freelist); |
1805 | ASSERT(xfs_Gqm->qm_dqzone != NULL); | 1738 | xfs_qm_dqfree_one(dqp); |
1806 | *O_dqpp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP); | 1739 | } |
1807 | atomic_inc(&xfs_Gqm->qm_totaldquots); | 1740 | out: |
1808 | 1741 | return (xfs_Gqm->qm_dqfrlist_cnt / 100) * sysctl_vfs_cache_pressure; | |
1809 | return B_TRUE; | ||
1810 | } | 1742 | } |
1811 | 1743 | ||
1812 | |||
1813 | /* | 1744 | /* |
1814 | * Start a transaction and write the incore superblock changes to | 1745 | * Start a transaction and write the incore superblock changes to |
1815 | * disk. flags parameter indicates which fields have changed. | 1746 | * disk. flags parameter indicates which fields have changed. |
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h index 9b4f3adefbc5..9a9b997e1a0a 100644 --- a/fs/xfs/xfs_qm.h +++ b/fs/xfs/xfs_qm.h | |||
@@ -26,24 +26,12 @@ | |||
26 | struct xfs_qm; | 26 | struct xfs_qm; |
27 | struct xfs_inode; | 27 | struct xfs_inode; |
28 | 28 | ||
29 | extern uint ndquot; | ||
30 | extern struct mutex xfs_Gqm_lock; | 29 | extern struct mutex xfs_Gqm_lock; |
31 | extern struct xfs_qm *xfs_Gqm; | 30 | extern struct xfs_qm *xfs_Gqm; |
32 | extern kmem_zone_t *qm_dqzone; | 31 | extern kmem_zone_t *qm_dqzone; |
33 | extern kmem_zone_t *qm_dqtrxzone; | 32 | extern kmem_zone_t *qm_dqtrxzone; |
34 | 33 | ||
35 | /* | 34 | /* |
36 | * Ditto, for xfs_qm_dqreclaim_one. | ||
37 | */ | ||
38 | #define XFS_QM_RECLAIM_MAX_RESTARTS 4 | ||
39 | |||
40 | /* | ||
41 | * Ideal ratio of free to in use dquots. Quota manager makes an attempt | ||
42 | * to keep this balance. | ||
43 | */ | ||
44 | #define XFS_QM_DQFREE_RATIO 2 | ||
45 | |||
46 | /* | ||
47 | * Dquot hashtable constants/threshold values. | 35 | * Dquot hashtable constants/threshold values. |
48 | */ | 36 | */ |
49 | #define XFS_QM_HASHSIZE_LOW (PAGE_SIZE / sizeof(xfs_dqhash_t)) | 37 | #define XFS_QM_HASHSIZE_LOW (PAGE_SIZE / sizeof(xfs_dqhash_t)) |
@@ -74,7 +62,6 @@ typedef struct xfs_qm { | |||
74 | int qm_dqfrlist_cnt; | 62 | int qm_dqfrlist_cnt; |
75 | atomic_t qm_totaldquots; /* total incore dquots */ | 63 | atomic_t qm_totaldquots; /* total incore dquots */ |
76 | uint qm_nrefs; /* file systems with quota on */ | 64 | uint qm_nrefs; /* file systems with quota on */ |
77 | int qm_dqfree_ratio;/* ratio of free to inuse dquots */ | ||
78 | kmem_zone_t *qm_dqzone; /* dquot mem-alloc zone */ | 65 | kmem_zone_t *qm_dqzone; /* dquot mem-alloc zone */ |
79 | kmem_zone_t *qm_dqtrxzone; /* t_dqinfo of transactions */ | 66 | kmem_zone_t *qm_dqtrxzone; /* t_dqinfo of transactions */ |
80 | } xfs_qm_t; | 67 | } xfs_qm_t; |
@@ -143,7 +130,6 @@ extern int xfs_qm_quotacheck(xfs_mount_t *); | |||
143 | extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); | 130 | extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); |
144 | 131 | ||
145 | /* dquot stuff */ | 132 | /* dquot stuff */ |
146 | extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **); | ||
147 | extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint); | 133 | extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint); |
148 | extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); | 134 | extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); |
149 | 135 | ||
diff --git a/fs/xfs/xfs_qm_stats.c b/fs/xfs/xfs_qm_stats.c index 8671a0b32644..5729ba570877 100644 --- a/fs/xfs/xfs_qm_stats.c +++ b/fs/xfs/xfs_qm_stats.c | |||
@@ -42,9 +42,9 @@ static int xqm_proc_show(struct seq_file *m, void *v) | |||
42 | { | 42 | { |
43 | /* maximum; incore; ratio free to inuse; freelist */ | 43 | /* maximum; incore; ratio free to inuse; freelist */ |
44 | seq_printf(m, "%d\t%d\t%d\t%u\n", | 44 | seq_printf(m, "%d\t%d\t%d\t%u\n", |
45 | ndquot, | 45 | 0, |
46 | xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0, | 46 | xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0, |
47 | xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0, | 47 | 0, |
48 | xfs_Gqm? xfs_Gqm->qm_dqfrlist_cnt : 0); | 48 | xfs_Gqm? xfs_Gqm->qm_dqfrlist_cnt : 0); |
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 6b6df5802e95..bb134a819930 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h | |||
@@ -733,11 +733,10 @@ DEFINE_EVENT(xfs_dquot_class, name, \ | |||
733 | DEFINE_DQUOT_EVENT(xfs_dqadjust); | 733 | DEFINE_DQUOT_EVENT(xfs_dqadjust); |
734 | DEFINE_DQUOT_EVENT(xfs_dqreclaim_want); | 734 | DEFINE_DQUOT_EVENT(xfs_dqreclaim_want); |
735 | DEFINE_DQUOT_EVENT(xfs_dqreclaim_dirty); | 735 | DEFINE_DQUOT_EVENT(xfs_dqreclaim_dirty); |
736 | DEFINE_DQUOT_EVENT(xfs_dqreclaim_unlink); | 736 | DEFINE_DQUOT_EVENT(xfs_dqreclaim_busy); |
737 | DEFINE_DQUOT_EVENT(xfs_dqreclaim_done); | ||
737 | DEFINE_DQUOT_EVENT(xfs_dqattach_found); | 738 | DEFINE_DQUOT_EVENT(xfs_dqattach_found); |
738 | DEFINE_DQUOT_EVENT(xfs_dqattach_get); | 739 | DEFINE_DQUOT_EVENT(xfs_dqattach_get); |
739 | DEFINE_DQUOT_EVENT(xfs_dqinit); | ||
740 | DEFINE_DQUOT_EVENT(xfs_dqreuse); | ||
741 | DEFINE_DQUOT_EVENT(xfs_dqalloc); | 740 | DEFINE_DQUOT_EVENT(xfs_dqalloc); |
742 | DEFINE_DQUOT_EVENT(xfs_dqtobp_read); | 741 | DEFINE_DQUOT_EVENT(xfs_dqtobp_read); |
743 | DEFINE_DQUOT_EVENT(xfs_dqread); | 742 | DEFINE_DQUOT_EVENT(xfs_dqread); |