diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bio.c | 4 | ||||
-rw-r--r-- | fs/cifs/CHANGES | 3 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifspdu.h | 6 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 7 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 360 | ||||
-rw-r--r-- | fs/cifs/connect.c | 8 | ||||
-rw-r--r-- | fs/cifs/inode.c | 3 | ||||
-rw-r--r-- | fs/cifs/misc.c | 2 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 8 | ||||
-rw-r--r-- | fs/ext4/ext4.h | 2 | ||||
-rw-r--r-- | fs/fuse/dev.c | 30 | ||||
-rw-r--r-- | fs/gfs2/aops.c | 4 | ||||
-rw-r--r-- | fs/gfs2/glock.c | 75 | ||||
-rw-r--r-- | fs/gfs2/glock.h | 7 | ||||
-rw-r--r-- | fs/gfs2/glops.c | 16 | ||||
-rw-r--r-- | fs/gfs2/incore.h | 5 | ||||
-rw-r--r-- | fs/gfs2/inode.c | 6 | ||||
-rw-r--r-- | fs/gfs2/lock_dlm.c | 5 | ||||
-rw-r--r-- | fs/gfs2/lops.c | 4 | ||||
-rw-r--r-- | fs/gfs2/main.c | 28 | ||||
-rw-r--r-- | fs/gfs2/meta_io.c | 46 | ||||
-rw-r--r-- | fs/gfs2/meta_io.h | 12 | ||||
-rw-r--r-- | fs/gfs2/ops_fstype.c | 4 | ||||
-rw-r--r-- | fs/gfs2/super.c | 27 | ||||
-rw-r--r-- | fs/gfs2/sys.c | 2 | ||||
-rw-r--r-- | fs/gfs2/util.c | 1 | ||||
-rw-r--r-- | fs/gfs2/util.h | 1 | ||||
-rw-r--r-- | fs/nfs/iostat.h | 4 | ||||
-rw-r--r-- | fs/proc/kmsg.c | 14 | ||||
-rw-r--r-- | fs/seq_file.c | 130 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 2 |
32 files changed, 408 insertions, 420 deletions
@@ -555,7 +555,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page | |||
555 | .bi_rw = bio->bi_rw, | 555 | .bi_rw = bio->bi_rw, |
556 | }; | 556 | }; |
557 | 557 | ||
558 | if (q->merge_bvec_fn(q, &bvm, prev) != prev->bv_len) { | 558 | if (q->merge_bvec_fn(q, &bvm, prev) < len) { |
559 | prev->bv_len -= len; | 559 | prev->bv_len -= len; |
560 | return 0; | 560 | return 0; |
561 | } | 561 | } |
@@ -608,7 +608,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page | |||
608 | * merge_bvec_fn() returns number of bytes it can accept | 608 | * merge_bvec_fn() returns number of bytes it can accept |
609 | * at this offset | 609 | * at this offset |
610 | */ | 610 | */ |
611 | if (q->merge_bvec_fn(q, &bvm, bvec) != bvec->bv_len) { | 611 | if (q->merge_bvec_fn(q, &bvm, bvec) < len) { |
612 | bvec->bv_page = NULL; | 612 | bvec->bv_page = NULL; |
613 | bvec->bv_len = 0; | 613 | bvec->bv_len = 0; |
614 | bvec->bv_offset = 0; | 614 | bvec->bv_offset = 0; |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 49503d2edc7e..bc0025cdd1c9 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
@@ -1,6 +1,7 @@ | |||
1 | Version 1.62 | 1 | Version 1.62 |
2 | ------------ | 2 | ------------ |
3 | Add sockopt=TCP_NODELAY mount option. | 3 | Add sockopt=TCP_NODELAY mount option. EA (xattr) routines hardened |
4 | to more strictly handle corrupt frames. | ||
4 | 5 | ||
5 | Version 1.61 | 6 | Version 1.61 |
6 | ------------ | 7 | ------------ |
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index ed751bb657db..a1c817eb291a 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -205,7 +205,7 @@ struct cifsUidInfo { | |||
205 | struct cifsSesInfo { | 205 | struct cifsSesInfo { |
206 | struct list_head smb_ses_list; | 206 | struct list_head smb_ses_list; |
207 | struct list_head tcon_list; | 207 | struct list_head tcon_list; |
208 | struct semaphore sesSem; | 208 | struct mutex session_mutex; |
209 | #if 0 | 209 | #if 0 |
210 | struct cifsUidInfo *uidInfo; /* pointer to user info */ | 210 | struct cifsUidInfo *uidInfo; /* pointer to user info */ |
211 | #endif | 211 | #endif |
diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 3877737f96a6..14d036d8db11 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h | |||
@@ -415,10 +415,10 @@ struct smb_hdr { | |||
415 | __u8 WordCount; | 415 | __u8 WordCount; |
416 | } __attribute__((packed)); | 416 | } __attribute__((packed)); |
417 | /* given a pointer to an smb_hdr retrieve the value of byte count */ | 417 | /* given a pointer to an smb_hdr retrieve the value of byte count */ |
418 | #define BCC(smb_var) (*(__u16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) | 418 | #define BCC(smb_var) (*(__u16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount))) |
419 | #define BCC_LE(smb_var) (*(__le16 *)((char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount))) | 419 | #define BCC_LE(smb_var) (*(__le16 *)((char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount))) |
420 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ | 420 | /* given a pointer to an smb_hdr retrieve the pointer to the byte area */ |
421 | #define pByteArea(smb_var) ((unsigned char *)smb_var + sizeof(struct smb_hdr) + (2 * smb_var->WordCount) + 2) | 421 | #define pByteArea(smb_var) ((unsigned char *)(smb_var) + sizeof(struct smb_hdr) + (2 * (smb_var)->WordCount) + 2) |
422 | 422 | ||
423 | /* | 423 | /* |
424 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) | 424 | * Computer Name Length (since Netbios name was length 16 with last byte 0x20) |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 5646727e33f5..88e2bc44ac58 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -363,13 +363,10 @@ extern int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
363 | __u32 filter, struct file *file, int multishot, | 363 | __u32 filter, struct file *file, int multishot, |
364 | const struct nls_table *nls_codepage); | 364 | const struct nls_table *nls_codepage); |
365 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 365 | extern ssize_t CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, |
366 | const unsigned char *searchName, char *EAData, | 366 | const unsigned char *searchName, |
367 | const unsigned char *ea_name, char *EAData, | ||
367 | size_t bufsize, const struct nls_table *nls_codepage, | 368 | size_t bufsize, const struct nls_table *nls_codepage, |
368 | int remap_special_chars); | 369 | int remap_special_chars); |
369 | extern ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon, | ||
370 | const unsigned char *searchName, const unsigned char *ea_name, | ||
371 | unsigned char *ea_value, size_t buf_size, | ||
372 | const struct nls_table *nls_codepage, int remap_special_chars); | ||
373 | extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, | 370 | extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon, |
374 | const char *fileName, const char *ea_name, | 371 | const char *fileName, const char *ea_name, |
375 | const void *ea_value, const __u16 ea_value_len, | 372 | const void *ea_value, const __u16 ea_value_len, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 941441d3e386..9d17df3e0768 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -170,19 +170,19 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command) | |||
170 | * need to prevent multiple threads trying to simultaneously | 170 | * need to prevent multiple threads trying to simultaneously |
171 | * reconnect the same SMB session | 171 | * reconnect the same SMB session |
172 | */ | 172 | */ |
173 | down(&ses->sesSem); | 173 | mutex_lock(&ses->session_mutex); |
174 | if (ses->need_reconnect) | 174 | if (ses->need_reconnect) |
175 | rc = cifs_setup_session(0, ses, nls_codepage); | 175 | rc = cifs_setup_session(0, ses, nls_codepage); |
176 | 176 | ||
177 | /* do we need to reconnect tcon? */ | 177 | /* do we need to reconnect tcon? */ |
178 | if (rc || !tcon->need_reconnect) { | 178 | if (rc || !tcon->need_reconnect) { |
179 | up(&ses->sesSem); | 179 | mutex_unlock(&ses->session_mutex); |
180 | goto out; | 180 | goto out; |
181 | } | 181 | } |
182 | 182 | ||
183 | mark_open_files_invalid(tcon); | 183 | mark_open_files_invalid(tcon); |
184 | rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage); | 184 | rc = CIFSTCon(0, ses, tcon->treeName, tcon, nls_codepage); |
185 | up(&ses->sesSem); | 185 | mutex_unlock(&ses->session_mutex); |
186 | cFYI(1, ("reconnect tcon rc = %d", rc)); | 186 | cFYI(1, ("reconnect tcon rc = %d", rc)); |
187 | 187 | ||
188 | if (rc) | 188 | if (rc) |
@@ -700,13 +700,13 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
700 | if (!ses || !ses->server) | 700 | if (!ses || !ses->server) |
701 | return -EIO; | 701 | return -EIO; |
702 | 702 | ||
703 | down(&ses->sesSem); | 703 | mutex_lock(&ses->session_mutex); |
704 | if (ses->need_reconnect) | 704 | if (ses->need_reconnect) |
705 | goto session_already_dead; /* no need to send SMBlogoff if uid | 705 | goto session_already_dead; /* no need to send SMBlogoff if uid |
706 | already closed due to reconnect */ | 706 | already closed due to reconnect */ |
707 | rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB); | 707 | rc = small_smb_init(SMB_COM_LOGOFF_ANDX, 2, NULL, (void **)&pSMB); |
708 | if (rc) { | 708 | if (rc) { |
709 | up(&ses->sesSem); | 709 | mutex_unlock(&ses->session_mutex); |
710 | return rc; | 710 | return rc; |
711 | } | 711 | } |
712 | 712 | ||
@@ -721,7 +721,7 @@ CIFSSMBLogoff(const int xid, struct cifsSesInfo *ses) | |||
721 | pSMB->AndXCommand = 0xFF; | 721 | pSMB->AndXCommand = 0xFF; |
722 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); | 722 | rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); |
723 | session_already_dead: | 723 | session_already_dead: |
724 | up(&ses->sesSem); | 724 | mutex_unlock(&ses->session_mutex); |
725 | 725 | ||
726 | /* if session dead then we do not need to do ulogoff, | 726 | /* if session dead then we do not need to do ulogoff, |
727 | since server closed smb session, no sense reporting | 727 | since server closed smb session, no sense reporting |
@@ -5269,22 +5269,34 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon, | |||
5269 | cifs_buf_release(pSMB); | 5269 | cifs_buf_release(pSMB); |
5270 | return rc; | 5270 | return rc; |
5271 | } | 5271 | } |
5272 | |||
5272 | #ifdef CONFIG_CIFS_XATTR | 5273 | #ifdef CONFIG_CIFS_XATTR |
5274 | /* | ||
5275 | * Do a path-based QUERY_ALL_EAS call and parse the result. This is a common | ||
5276 | * function used by listxattr and getxattr type calls. When ea_name is set, | ||
5277 | * it looks for that attribute name and stuffs that value into the EAData | ||
5278 | * buffer. When ea_name is NULL, it stuffs a list of attribute names into the | ||
5279 | * buffer. In both cases, the return value is either the length of the | ||
5280 | * resulting data or a negative error code. If EAData is a NULL pointer then | ||
5281 | * the data isn't copied to it, but the length is returned. | ||
5282 | */ | ||
5273 | ssize_t | 5283 | ssize_t |
5274 | CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, | 5284 | CIFSSMBQAllEAs(const int xid, struct cifsTconInfo *tcon, |
5275 | const unsigned char *searchName, | 5285 | const unsigned char *searchName, const unsigned char *ea_name, |
5276 | char *EAData, size_t buf_size, | 5286 | char *EAData, size_t buf_size, |
5277 | const struct nls_table *nls_codepage, int remap) | 5287 | const struct nls_table *nls_codepage, int remap) |
5278 | { | 5288 | { |
5279 | /* BB assumes one setup word */ | 5289 | /* BB assumes one setup word */ |
5280 | TRANSACTION2_QPI_REQ *pSMB = NULL; | 5290 | TRANSACTION2_QPI_REQ *pSMB = NULL; |
5281 | TRANSACTION2_QPI_RSP *pSMBr = NULL; | 5291 | TRANSACTION2_QPI_RSP *pSMBr = NULL; |
5282 | int rc = 0; | 5292 | int rc = 0; |
5283 | int bytes_returned; | 5293 | int bytes_returned; |
5284 | int name_len; | 5294 | int list_len; |
5295 | struct fealist *ea_response_data; | ||
5285 | struct fea *temp_fea; | 5296 | struct fea *temp_fea; |
5286 | char *temp_ptr; | 5297 | char *temp_ptr; |
5287 | __u16 params, byte_count; | 5298 | char *end_of_smb; |
5299 | __u16 params, byte_count, data_offset; | ||
5288 | 5300 | ||
5289 | cFYI(1, ("In Query All EAs path %s", searchName)); | 5301 | cFYI(1, ("In Query All EAs path %s", searchName)); |
5290 | QAllEAsRetry: | 5302 | QAllEAsRetry: |
@@ -5294,22 +5306,22 @@ QAllEAsRetry: | |||
5294 | return rc; | 5306 | return rc; |
5295 | 5307 | ||
5296 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 5308 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { |
5297 | name_len = | 5309 | list_len = |
5298 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, | 5310 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, |
5299 | PATH_MAX, nls_codepage, remap); | 5311 | PATH_MAX, nls_codepage, remap); |
5300 | name_len++; /* trailing null */ | 5312 | list_len++; /* trailing null */ |
5301 | name_len *= 2; | 5313 | list_len *= 2; |
5302 | } else { /* BB improve the check for buffer overruns BB */ | 5314 | } else { /* BB improve the check for buffer overruns BB */ |
5303 | name_len = strnlen(searchName, PATH_MAX); | 5315 | list_len = strnlen(searchName, PATH_MAX); |
5304 | name_len++; /* trailing null */ | 5316 | list_len++; /* trailing null */ |
5305 | strncpy(pSMB->FileName, searchName, name_len); | 5317 | strncpy(pSMB->FileName, searchName, list_len); |
5306 | } | 5318 | } |
5307 | 5319 | ||
5308 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; | 5320 | params = 2 /* level */ + 4 /* reserved */ + list_len /* includes NUL */; |
5309 | pSMB->TotalDataCount = 0; | 5321 | pSMB->TotalDataCount = 0; |
5310 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5322 | pSMB->MaxParameterCount = cpu_to_le16(2); |
5311 | /* BB find exact max SMB PDU from sess structure BB */ | 5323 | /* BB find exact max SMB PDU from sess structure BB */ |
5312 | pSMB->MaxDataCount = cpu_to_le16(4000); | 5324 | pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize); |
5313 | pSMB->MaxSetupCount = 0; | 5325 | pSMB->MaxSetupCount = 0; |
5314 | pSMB->Reserved = 0; | 5326 | pSMB->Reserved = 0; |
5315 | pSMB->Flags = 0; | 5327 | pSMB->Flags = 0; |
@@ -5334,237 +5346,117 @@ QAllEAsRetry: | |||
5334 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5346 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); |
5335 | if (rc) { | 5347 | if (rc) { |
5336 | cFYI(1, ("Send error in QueryAllEAs = %d", rc)); | 5348 | cFYI(1, ("Send error in QueryAllEAs = %d", rc)); |
5337 | } else { /* decode response */ | 5349 | goto QAllEAsOut; |
5338 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 5350 | } |
5339 | 5351 | ||
5340 | /* BB also check enough total bytes returned */ | 5352 | |
5341 | /* BB we need to improve the validity checking | 5353 | /* BB also check enough total bytes returned */ |
5342 | of these trans2 responses */ | 5354 | /* BB we need to improve the validity checking |
5343 | if (rc || (pSMBr->ByteCount < 4)) | 5355 | of these trans2 responses */ |
5344 | rc = -EIO; /* bad smb */ | 5356 | |
5345 | /* else if (pFindData){ | 5357 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); |
5346 | memcpy((char *) pFindData, | 5358 | if (rc || (pSMBr->ByteCount < 4)) { |
5347 | (char *) &pSMBr->hdr.Protocol + | 5359 | rc = -EIO; /* bad smb */ |
5348 | data_offset, kl); | 5360 | goto QAllEAsOut; |
5349 | }*/ else { | ||
5350 | /* check that length of list is not more than bcc */ | ||
5351 | /* check that each entry does not go beyond length | ||
5352 | of list */ | ||
5353 | /* check that each element of each entry does not | ||
5354 | go beyond end of list */ | ||
5355 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | ||
5356 | struct fealist *ea_response_data; | ||
5357 | rc = 0; | ||
5358 | /* validate_trans2_offsets() */ | ||
5359 | /* BB check if start of smb + data_offset > &bcc+ bcc */ | ||
5360 | ea_response_data = (struct fealist *) | ||
5361 | (((char *) &pSMBr->hdr.Protocol) + | ||
5362 | data_offset); | ||
5363 | name_len = le32_to_cpu(ea_response_data->list_len); | ||
5364 | cFYI(1, ("ea length %d", name_len)); | ||
5365 | if (name_len <= 8) { | ||
5366 | /* returned EA size zeroed at top of function */ | ||
5367 | cFYI(1, ("empty EA list returned from server")); | ||
5368 | } else { | ||
5369 | /* account for ea list len */ | ||
5370 | name_len -= 4; | ||
5371 | temp_fea = ea_response_data->list; | ||
5372 | temp_ptr = (char *)temp_fea; | ||
5373 | while (name_len > 0) { | ||
5374 | __u16 value_len; | ||
5375 | name_len -= 4; | ||
5376 | temp_ptr += 4; | ||
5377 | rc += temp_fea->name_len; | ||
5378 | /* account for prefix user. and trailing null */ | ||
5379 | rc = rc + 5 + 1; | ||
5380 | if (rc < (int)buf_size) { | ||
5381 | memcpy(EAData, "user.", 5); | ||
5382 | EAData += 5; | ||
5383 | memcpy(EAData, temp_ptr, | ||
5384 | temp_fea->name_len); | ||
5385 | EAData += temp_fea->name_len; | ||
5386 | /* null terminate name */ | ||
5387 | *EAData = 0; | ||
5388 | EAData = EAData + 1; | ||
5389 | } else if (buf_size == 0) { | ||
5390 | /* skip copy - calc size only */ | ||
5391 | } else { | ||
5392 | /* stop before overrun buffer */ | ||
5393 | rc = -ERANGE; | ||
5394 | break; | ||
5395 | } | ||
5396 | name_len -= temp_fea->name_len; | ||
5397 | temp_ptr += temp_fea->name_len; | ||
5398 | /* account for trailing null */ | ||
5399 | name_len--; | ||
5400 | temp_ptr++; | ||
5401 | value_len = | ||
5402 | le16_to_cpu(temp_fea->value_len); | ||
5403 | name_len -= value_len; | ||
5404 | temp_ptr += value_len; | ||
5405 | /* BB check that temp_ptr is still | ||
5406 | within the SMB BB*/ | ||
5407 | |||
5408 | /* no trailing null to account for | ||
5409 | in value len */ | ||
5410 | /* go on to next EA */ | ||
5411 | temp_fea = (struct fea *)temp_ptr; | ||
5412 | } | ||
5413 | } | ||
5414 | } | ||
5415 | } | 5361 | } |
5416 | cifs_buf_release(pSMB); | ||
5417 | if (rc == -EAGAIN) | ||
5418 | goto QAllEAsRetry; | ||
5419 | 5362 | ||
5420 | return (ssize_t)rc; | 5363 | /* check that length of list is not more than bcc */ |
5421 | } | 5364 | /* check that each entry does not go beyond length |
5365 | of list */ | ||
5366 | /* check that each element of each entry does not | ||
5367 | go beyond end of list */ | ||
5368 | /* validate_trans2_offsets() */ | ||
5369 | /* BB check if start of smb + data_offset > &bcc+ bcc */ | ||
5422 | 5370 | ||
5423 | ssize_t CIFSSMBQueryEA(const int xid, struct cifsTconInfo *tcon, | 5371 | data_offset = le16_to_cpu(pSMBr->t2.DataOffset); |
5424 | const unsigned char *searchName, const unsigned char *ea_name, | 5372 | ea_response_data = (struct fealist *) |
5425 | unsigned char *ea_value, size_t buf_size, | 5373 | (((char *) &pSMBr->hdr.Protocol) + data_offset); |
5426 | const struct nls_table *nls_codepage, int remap) | ||
5427 | { | ||
5428 | TRANSACTION2_QPI_REQ *pSMB = NULL; | ||
5429 | TRANSACTION2_QPI_RSP *pSMBr = NULL; | ||
5430 | int rc = 0; | ||
5431 | int bytes_returned; | ||
5432 | int name_len; | ||
5433 | struct fea *temp_fea; | ||
5434 | char *temp_ptr; | ||
5435 | __u16 params, byte_count; | ||
5436 | 5374 | ||
5437 | cFYI(1, ("In Query EA path %s", searchName)); | 5375 | list_len = le32_to_cpu(ea_response_data->list_len); |
5438 | QEARetry: | 5376 | cFYI(1, ("ea length %d", list_len)); |
5439 | rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB, | 5377 | if (list_len <= 8) { |
5440 | (void **) &pSMBr); | 5378 | cFYI(1, ("empty EA list returned from server")); |
5441 | if (rc) | 5379 | goto QAllEAsOut; |
5442 | return rc; | 5380 | } |
5443 | 5381 | ||
5444 | if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { | 5382 | /* make sure list_len doesn't go past end of SMB */ |
5445 | name_len = | 5383 | end_of_smb = (char *)pByteArea(&pSMBr->hdr) + BCC(&pSMBr->hdr); |
5446 | cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, | 5384 | if ((char *)ea_response_data + list_len > end_of_smb) { |
5447 | PATH_MAX, nls_codepage, remap); | 5385 | cFYI(1, ("EA list appears to go beyond SMB")); |
5448 | name_len++; /* trailing null */ | 5386 | rc = -EIO; |
5449 | name_len *= 2; | 5387 | goto QAllEAsOut; |
5450 | } else { /* BB improve the check for buffer overruns BB */ | ||
5451 | name_len = strnlen(searchName, PATH_MAX); | ||
5452 | name_len++; /* trailing null */ | ||
5453 | strncpy(pSMB->FileName, searchName, name_len); | ||
5454 | } | 5388 | } |
5455 | 5389 | ||
5456 | params = 2 /* level */ + 4 /* reserved */ + name_len /* includes NUL */; | 5390 | /* account for ea list len */ |
5457 | pSMB->TotalDataCount = 0; | 5391 | list_len -= 4; |
5458 | pSMB->MaxParameterCount = cpu_to_le16(2); | 5392 | temp_fea = ea_response_data->list; |
5459 | /* BB find exact max SMB PDU from sess structure BB */ | 5393 | temp_ptr = (char *)temp_fea; |
5460 | pSMB->MaxDataCount = cpu_to_le16(4000); | 5394 | while (list_len > 0) { |
5461 | pSMB->MaxSetupCount = 0; | 5395 | unsigned int name_len; |
5462 | pSMB->Reserved = 0; | 5396 | __u16 value_len; |
5463 | pSMB->Flags = 0; | 5397 | |
5464 | pSMB->Timeout = 0; | 5398 | list_len -= 4; |
5465 | pSMB->Reserved2 = 0; | 5399 | temp_ptr += 4; |
5466 | pSMB->ParameterOffset = cpu_to_le16(offsetof( | 5400 | /* make sure we can read name_len and value_len */ |
5467 | struct smb_com_transaction2_qpi_req, InformationLevel) - 4); | 5401 | if (list_len < 0) { |
5468 | pSMB->DataCount = 0; | 5402 | cFYI(1, ("EA entry goes beyond length of list")); |
5469 | pSMB->DataOffset = 0; | 5403 | rc = -EIO; |
5470 | pSMB->SetupCount = 1; | 5404 | goto QAllEAsOut; |
5471 | pSMB->Reserved3 = 0; | 5405 | } |
5472 | pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION); | ||
5473 | byte_count = params + 1 /* pad */ ; | ||
5474 | pSMB->TotalParameterCount = cpu_to_le16(params); | ||
5475 | pSMB->ParameterCount = pSMB->TotalParameterCount; | ||
5476 | pSMB->InformationLevel = cpu_to_le16(SMB_INFO_QUERY_ALL_EAS); | ||
5477 | pSMB->Reserved4 = 0; | ||
5478 | pSMB->hdr.smb_buf_length += byte_count; | ||
5479 | pSMB->ByteCount = cpu_to_le16(byte_count); | ||
5480 | 5406 | ||
5481 | rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB, | 5407 | name_len = temp_fea->name_len; |
5482 | (struct smb_hdr *) pSMBr, &bytes_returned, 0); | 5408 | value_len = le16_to_cpu(temp_fea->value_len); |
5483 | if (rc) { | 5409 | list_len -= name_len + 1 + value_len; |
5484 | cFYI(1, ("Send error in Query EA = %d", rc)); | 5410 | if (list_len < 0) { |
5485 | } else { /* decode response */ | 5411 | cFYI(1, ("EA entry goes beyond length of list")); |
5486 | rc = validate_t2((struct smb_t2_rsp *)pSMBr); | 5412 | rc = -EIO; |
5413 | goto QAllEAsOut; | ||
5414 | } | ||
5487 | 5415 | ||
5488 | /* BB also check enough total bytes returned */ | 5416 | if (ea_name) { |
5489 | /* BB we need to improve the validity checking | 5417 | if (strncmp(ea_name, temp_ptr, name_len) == 0) { |
5490 | of these trans2 responses */ | 5418 | temp_ptr += name_len + 1; |
5491 | if (rc || (pSMBr->ByteCount < 4)) | 5419 | rc = value_len; |
5492 | rc = -EIO; /* bad smb */ | 5420 | if (buf_size == 0) |
5493 | /* else if (pFindData){ | 5421 | goto QAllEAsOut; |
5494 | memcpy((char *) pFindData, | 5422 | if ((size_t)value_len > buf_size) { |
5495 | (char *) &pSMBr->hdr.Protocol + | 5423 | rc = -ERANGE; |
5496 | data_offset, kl); | 5424 | goto QAllEAsOut; |
5497 | }*/ else { | ||
5498 | /* check that length of list is not more than bcc */ | ||
5499 | /* check that each entry does not go beyond length | ||
5500 | of list */ | ||
5501 | /* check that each element of each entry does not | ||
5502 | go beyond end of list */ | ||
5503 | __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); | ||
5504 | struct fealist *ea_response_data; | ||
5505 | rc = -ENODATA; | ||
5506 | /* validate_trans2_offsets() */ | ||
5507 | /* BB check if start of smb + data_offset > &bcc+ bcc*/ | ||
5508 | ea_response_data = (struct fealist *) | ||
5509 | (((char *) &pSMBr->hdr.Protocol) + | ||
5510 | data_offset); | ||
5511 | name_len = le32_to_cpu(ea_response_data->list_len); | ||
5512 | cFYI(1, ("ea length %d", name_len)); | ||
5513 | if (name_len <= 8) { | ||
5514 | /* returned EA size zeroed at top of function */ | ||
5515 | cFYI(1, ("empty EA list returned from server")); | ||
5516 | } else { | ||
5517 | /* account for ea list len */ | ||
5518 | name_len -= 4; | ||
5519 | temp_fea = ea_response_data->list; | ||
5520 | temp_ptr = (char *)temp_fea; | ||
5521 | /* loop through checking if we have a matching | ||
5522 | name and then return the associated value */ | ||
5523 | while (name_len > 0) { | ||
5524 | __u16 value_len; | ||
5525 | name_len -= 4; | ||
5526 | temp_ptr += 4; | ||
5527 | value_len = | ||
5528 | le16_to_cpu(temp_fea->value_len); | ||
5529 | /* BB validate that value_len falls within SMB, | ||
5530 | even though maximum for name_len is 255 */ | ||
5531 | if (memcmp(temp_fea->name, ea_name, | ||
5532 | temp_fea->name_len) == 0) { | ||
5533 | /* found a match */ | ||
5534 | rc = value_len; | ||
5535 | /* account for prefix user. and trailing null */ | ||
5536 | if (rc <= (int)buf_size) { | ||
5537 | memcpy(ea_value, | ||
5538 | temp_fea->name+temp_fea->name_len+1, | ||
5539 | rc); | ||
5540 | /* ea values, unlike ea | ||
5541 | names, are not null | ||
5542 | terminated */ | ||
5543 | } else if (buf_size == 0) { | ||
5544 | /* skip copy - calc size only */ | ||
5545 | } else { | ||
5546 | /* stop before overrun buffer */ | ||
5547 | rc = -ERANGE; | ||
5548 | } | ||
5549 | break; | ||
5550 | } | ||
5551 | name_len -= temp_fea->name_len; | ||
5552 | temp_ptr += temp_fea->name_len; | ||
5553 | /* account for trailing null */ | ||
5554 | name_len--; | ||
5555 | temp_ptr++; | ||
5556 | name_len -= value_len; | ||
5557 | temp_ptr += value_len; | ||
5558 | /* No trailing null to account for in | ||
5559 | value_len. Go on to next EA */ | ||
5560 | temp_fea = (struct fea *)temp_ptr; | ||
5561 | } | 5425 | } |
5426 | memcpy(EAData, temp_ptr, value_len); | ||
5427 | goto QAllEAsOut; | ||
5428 | } | ||
5429 | } else { | ||
5430 | /* account for prefix user. and trailing null */ | ||
5431 | rc += (5 + 1 + name_len); | ||
5432 | if (rc < (int) buf_size) { | ||
5433 | memcpy(EAData, "user.", 5); | ||
5434 | EAData += 5; | ||
5435 | memcpy(EAData, temp_ptr, name_len); | ||
5436 | EAData += name_len; | ||
5437 | /* null terminate name */ | ||
5438 | *EAData = 0; | ||
5439 | ++EAData; | ||
5440 | } else if (buf_size == 0) { | ||
5441 | /* skip copy - calc size only */ | ||
5442 | } else { | ||
5443 | /* stop before overrun buffer */ | ||
5444 | rc = -ERANGE; | ||
5445 | break; | ||
5562 | } | 5446 | } |
5563 | } | 5447 | } |
5448 | temp_ptr += name_len + 1 + value_len; | ||
5449 | temp_fea = (struct fea *)temp_ptr; | ||
5564 | } | 5450 | } |
5451 | |||
5452 | /* didn't find the named attribute */ | ||
5453 | if (ea_name) | ||
5454 | rc = -ENODATA; | ||
5455 | |||
5456 | QAllEAsOut: | ||
5565 | cifs_buf_release(pSMB); | 5457 | cifs_buf_release(pSMB); |
5566 | if (rc == -EAGAIN) | 5458 | if (rc == -EAGAIN) |
5567 | goto QEARetry; | 5459 | goto QAllEAsRetry; |
5568 | 5460 | ||
5569 | return (ssize_t)rc; | 5461 | return (ssize_t)rc; |
5570 | } | 5462 | } |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 2e9e09ca0e30..45eb6cba793f 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -2388,13 +2388,13 @@ try_mount_again: | |||
2388 | */ | 2388 | */ |
2389 | cifs_put_tcp_session(srvTcp); | 2389 | cifs_put_tcp_session(srvTcp); |
2390 | 2390 | ||
2391 | down(&pSesInfo->sesSem); | 2391 | mutex_lock(&pSesInfo->session_mutex); |
2392 | if (pSesInfo->need_reconnect) { | 2392 | if (pSesInfo->need_reconnect) { |
2393 | cFYI(1, ("Session needs reconnect")); | 2393 | cFYI(1, ("Session needs reconnect")); |
2394 | rc = cifs_setup_session(xid, pSesInfo, | 2394 | rc = cifs_setup_session(xid, pSesInfo, |
2395 | cifs_sb->local_nls); | 2395 | cifs_sb->local_nls); |
2396 | } | 2396 | } |
2397 | up(&pSesInfo->sesSem); | 2397 | mutex_unlock(&pSesInfo->session_mutex); |
2398 | } else if (!rc) { | 2398 | } else if (!rc) { |
2399 | cFYI(1, ("Existing smb sess not found")); | 2399 | cFYI(1, ("Existing smb sess not found")); |
2400 | pSesInfo = sesInfoAlloc(); | 2400 | pSesInfo = sesInfoAlloc(); |
@@ -2437,12 +2437,12 @@ try_mount_again: | |||
2437 | } | 2437 | } |
2438 | pSesInfo->linux_uid = volume_info->linux_uid; | 2438 | pSesInfo->linux_uid = volume_info->linux_uid; |
2439 | pSesInfo->overrideSecFlg = volume_info->secFlg; | 2439 | pSesInfo->overrideSecFlg = volume_info->secFlg; |
2440 | down(&pSesInfo->sesSem); | 2440 | mutex_lock(&pSesInfo->session_mutex); |
2441 | 2441 | ||
2442 | /* BB FIXME need to pass vol->secFlgs BB */ | 2442 | /* BB FIXME need to pass vol->secFlgs BB */ |
2443 | rc = cifs_setup_session(xid, pSesInfo, | 2443 | rc = cifs_setup_session(xid, pSesInfo, |
2444 | cifs_sb->local_nls); | 2444 | cifs_sb->local_nls); |
2445 | up(&pSesInfo->sesSem); | 2445 | mutex_unlock(&pSesInfo->session_mutex); |
2446 | } | 2446 | } |
2447 | 2447 | ||
2448 | /* search for existing tcon to this server share */ | 2448 | /* search for existing tcon to this server share */ |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index e3fda978f481..8bdbc818164c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -111,6 +111,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) | |||
111 | 111 | ||
112 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; | 112 | cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING; |
113 | 113 | ||
114 | cifs_i->server_eof = fattr->cf_eof; | ||
114 | /* | 115 | /* |
115 | * Can't safely change the file size here if the client is writing to | 116 | * Can't safely change the file size here if the client is writing to |
116 | * it due to potential races. | 117 | * it due to potential races. |
@@ -366,7 +367,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path, | |||
366 | char ea_value[4]; | 367 | char ea_value[4]; |
367 | __u32 mode; | 368 | __u32 mode; |
368 | 369 | ||
369 | rc = CIFSSMBQueryEA(xid, cifs_sb->tcon, path, "SETFILEBITS", | 370 | rc = CIFSSMBQAllEAs(xid, cifs_sb->tcon, path, "SETFILEBITS", |
370 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, | 371 | ea_value, 4 /* size of buf */, cifs_sb->local_nls, |
371 | cifs_sb->mnt_cifs_flags & | 372 | cifs_sb->mnt_cifs_flags & |
372 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 373 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index d27d4ec6579b..d1474996a812 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
@@ -79,7 +79,7 @@ sesInfoAlloc(void) | |||
79 | ++ret_buf->ses_count; | 79 | ++ret_buf->ses_count; |
80 | INIT_LIST_HEAD(&ret_buf->smb_ses_list); | 80 | INIT_LIST_HEAD(&ret_buf->smb_ses_list); |
81 | INIT_LIST_HEAD(&ret_buf->tcon_list); | 81 | INIT_LIST_HEAD(&ret_buf->tcon_list); |
82 | init_MUTEX(&ret_buf->sesSem); | 82 | mutex_init(&ret_buf->session_mutex); |
83 | } | 83 | } |
84 | return ret_buf; | 84 | return ret_buf; |
85 | } | 85 | } |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index a75afa3dd9e1..3e2ef0de1209 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -244,7 +244,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
244 | /* revalidate/getattr then populate from inode */ | 244 | /* revalidate/getattr then populate from inode */ |
245 | } /* BB add else when above is implemented */ | 245 | } /* BB add else when above is implemented */ |
246 | ea_name += 5; /* skip past user. prefix */ | 246 | ea_name += 5; /* skip past user. prefix */ |
247 | rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value, | 247 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, |
248 | buf_size, cifs_sb->local_nls, | 248 | buf_size, cifs_sb->local_nls, |
249 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 249 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
250 | } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { | 250 | } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { |
@@ -252,7 +252,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
252 | goto get_ea_exit; | 252 | goto get_ea_exit; |
253 | 253 | ||
254 | ea_name += 4; /* skip past os2. prefix */ | 254 | ea_name += 4; /* skip past os2. prefix */ |
255 | rc = CIFSSMBQueryEA(xid, pTcon, full_path, ea_name, ea_value, | 255 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, |
256 | buf_size, cifs_sb->local_nls, | 256 | buf_size, cifs_sb->local_nls, |
257 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 257 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
258 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, | 258 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, |
@@ -364,8 +364,8 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
364 | /* if proc/fs/cifs/streamstoxattr is set then | 364 | /* if proc/fs/cifs/streamstoxattr is set then |
365 | search server for EAs or streams to | 365 | search server for EAs or streams to |
366 | returns as xattrs */ | 366 | returns as xattrs */ |
367 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, data, buf_size, | 367 | rc = CIFSSMBQAllEAs(xid, pTcon, full_path, NULL, data, |
368 | cifs_sb->local_nls, | 368 | buf_size, cifs_sb->local_nls, |
369 | cifs_sb->mnt_cifs_flags & | 369 | cifs_sb->mnt_cifs_flags & |
370 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 370 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
371 | 371 | ||
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 874d169a193e..4cedc91ec59d 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1014,7 +1014,7 @@ struct ext4_sb_info { | |||
1014 | atomic_t s_lock_busy; | 1014 | atomic_t s_lock_busy; |
1015 | 1015 | ||
1016 | /* locality groups */ | 1016 | /* locality groups */ |
1017 | struct ext4_locality_group *s_locality_groups; | 1017 | struct ext4_locality_group __percpu *s_locality_groups; |
1018 | 1018 | ||
1019 | /* for write statistics */ | 1019 | /* for write statistics */ |
1020 | unsigned long s_sectors_written_start; | 1020 | unsigned long s_sectors_written_start; |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 51d9e33d634f..eb7e9423691f 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -865,13 +865,10 @@ static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size, | |||
865 | 865 | ||
866 | down_read(&fc->killsb); | 866 | down_read(&fc->killsb); |
867 | err = -ENOENT; | 867 | err = -ENOENT; |
868 | if (!fc->sb) | 868 | if (fc->sb) { |
869 | goto err_unlock; | 869 | err = fuse_reverse_inval_inode(fc->sb, outarg.ino, |
870 | 870 | outarg.off, outarg.len); | |
871 | err = fuse_reverse_inval_inode(fc->sb, outarg.ino, | 871 | } |
872 | outarg.off, outarg.len); | ||
873 | |||
874 | err_unlock: | ||
875 | up_read(&fc->killsb); | 872 | up_read(&fc->killsb); |
876 | return err; | 873 | return err; |
877 | 874 | ||
@@ -884,10 +881,15 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, | |||
884 | struct fuse_copy_state *cs) | 881 | struct fuse_copy_state *cs) |
885 | { | 882 | { |
886 | struct fuse_notify_inval_entry_out outarg; | 883 | struct fuse_notify_inval_entry_out outarg; |
887 | int err = -EINVAL; | 884 | int err = -ENOMEM; |
888 | char buf[FUSE_NAME_MAX+1]; | 885 | char *buf; |
889 | struct qstr name; | 886 | struct qstr name; |
890 | 887 | ||
888 | buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL); | ||
889 | if (!buf) | ||
890 | goto err; | ||
891 | |||
892 | err = -EINVAL; | ||
891 | if (size < sizeof(outarg)) | 893 | if (size < sizeof(outarg)) |
892 | goto err; | 894 | goto err; |
893 | 895 | ||
@@ -910,16 +912,14 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, | |||
910 | 912 | ||
911 | down_read(&fc->killsb); | 913 | down_read(&fc->killsb); |
912 | err = -ENOENT; | 914 | err = -ENOENT; |
913 | if (!fc->sb) | 915 | if (fc->sb) |
914 | goto err_unlock; | 916 | err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name); |
915 | |||
916 | err = fuse_reverse_inval_entry(fc->sb, outarg.parent, &name); | ||
917 | |||
918 | err_unlock: | ||
919 | up_read(&fc->killsb); | 917 | up_read(&fc->killsb); |
918 | kfree(buf); | ||
920 | return err; | 919 | return err; |
921 | 920 | ||
922 | err: | 921 | err: |
922 | kfree(buf); | ||
923 | fuse_copy_finish(cs); | 923 | fuse_copy_finish(cs); |
924 | return err; | 924 | return err; |
925 | } | 925 | } |
diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 7b8da9415267..0c1d0b82dcf1 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c | |||
@@ -1061,8 +1061,8 @@ out: | |||
1061 | 1061 | ||
1062 | int gfs2_releasepage(struct page *page, gfp_t gfp_mask) | 1062 | int gfs2_releasepage(struct page *page, gfp_t gfp_mask) |
1063 | { | 1063 | { |
1064 | struct inode *aspace = page->mapping->host; | 1064 | struct address_space *mapping = page->mapping; |
1065 | struct gfs2_sbd *sdp = aspace->i_sb->s_fs_info; | 1065 | struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping); |
1066 | struct buffer_head *bh, *head; | 1066 | struct buffer_head *bh, *head; |
1067 | struct gfs2_bufdata *bd; | 1067 | struct gfs2_bufdata *bd; |
1068 | 1068 | ||
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index f42663325931..454d4b4eb36b 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
20 | #include <linux/wait.h> | 20 | #include <linux/wait.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/rwsem.h> | ||
23 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
24 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
25 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
@@ -60,7 +59,6 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl); | |||
60 | #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0) | 59 | #define GLOCK_BUG_ON(gl,x) do { if (unlikely(x)) { __dump_glock(NULL, gl); BUG(); } } while(0) |
61 | static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); | 60 | static void do_xmote(struct gfs2_glock *gl, struct gfs2_holder *gh, unsigned int target); |
62 | 61 | ||
63 | static DECLARE_RWSEM(gfs2_umount_flush_sem); | ||
64 | static struct dentry *gfs2_root; | 62 | static struct dentry *gfs2_root; |
65 | static struct workqueue_struct *glock_workqueue; | 63 | static struct workqueue_struct *glock_workqueue; |
66 | struct workqueue_struct *gfs2_delete_workqueue; | 64 | struct workqueue_struct *gfs2_delete_workqueue; |
@@ -154,12 +152,14 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp, | |||
154 | static void glock_free(struct gfs2_glock *gl) | 152 | static void glock_free(struct gfs2_glock *gl) |
155 | { | 153 | { |
156 | struct gfs2_sbd *sdp = gl->gl_sbd; | 154 | struct gfs2_sbd *sdp = gl->gl_sbd; |
157 | struct inode *aspace = gl->gl_aspace; | 155 | struct address_space *mapping = gfs2_glock2aspace(gl); |
156 | struct kmem_cache *cachep = gfs2_glock_cachep; | ||
158 | 157 | ||
159 | if (aspace) | 158 | GLOCK_BUG_ON(gl, mapping && mapping->nrpages); |
160 | gfs2_aspace_put(aspace); | ||
161 | trace_gfs2_glock_put(gl); | 159 | trace_gfs2_glock_put(gl); |
162 | sdp->sd_lockstruct.ls_ops->lm_put_lock(gfs2_glock_cachep, gl); | 160 | if (mapping) |
161 | cachep = gfs2_glock_aspace_cachep; | ||
162 | sdp->sd_lockstruct.ls_ops->lm_put_lock(cachep, gl); | ||
163 | } | 163 | } |
164 | 164 | ||
165 | /** | 165 | /** |
@@ -712,7 +712,6 @@ static void glock_work_func(struct work_struct *work) | |||
712 | finish_xmote(gl, gl->gl_reply); | 712 | finish_xmote(gl, gl->gl_reply); |
713 | drop_ref = 1; | 713 | drop_ref = 1; |
714 | } | 714 | } |
715 | down_read(&gfs2_umount_flush_sem); | ||
716 | spin_lock(&gl->gl_spin); | 715 | spin_lock(&gl->gl_spin); |
717 | if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && | 716 | if (test_and_clear_bit(GLF_PENDING_DEMOTE, &gl->gl_flags) && |
718 | gl->gl_state != LM_ST_UNLOCKED && | 717 | gl->gl_state != LM_ST_UNLOCKED && |
@@ -725,7 +724,6 @@ static void glock_work_func(struct work_struct *work) | |||
725 | } | 724 | } |
726 | run_queue(gl, 0); | 725 | run_queue(gl, 0); |
727 | spin_unlock(&gl->gl_spin); | 726 | spin_unlock(&gl->gl_spin); |
728 | up_read(&gfs2_umount_flush_sem); | ||
729 | if (!delay || | 727 | if (!delay || |
730 | queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) | 728 | queue_delayed_work(glock_workqueue, &gl->gl_work, delay) == 0) |
731 | gfs2_glock_put(gl); | 729 | gfs2_glock_put(gl); |
@@ -750,10 +748,11 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
750 | const struct gfs2_glock_operations *glops, int create, | 748 | const struct gfs2_glock_operations *glops, int create, |
751 | struct gfs2_glock **glp) | 749 | struct gfs2_glock **glp) |
752 | { | 750 | { |
751 | struct super_block *s = sdp->sd_vfs; | ||
753 | struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type }; | 752 | struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type }; |
754 | struct gfs2_glock *gl, *tmp; | 753 | struct gfs2_glock *gl, *tmp; |
755 | unsigned int hash = gl_hash(sdp, &name); | 754 | unsigned int hash = gl_hash(sdp, &name); |
756 | int error; | 755 | struct address_space *mapping; |
757 | 756 | ||
758 | read_lock(gl_lock_addr(hash)); | 757 | read_lock(gl_lock_addr(hash)); |
759 | gl = search_bucket(hash, sdp, &name); | 758 | gl = search_bucket(hash, sdp, &name); |
@@ -765,7 +764,10 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
765 | if (!create) | 764 | if (!create) |
766 | return -ENOENT; | 765 | return -ENOENT; |
767 | 766 | ||
768 | gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); | 767 | if (glops->go_flags & GLOF_ASPACE) |
768 | gl = kmem_cache_alloc(gfs2_glock_aspace_cachep, GFP_KERNEL); | ||
769 | else | ||
770 | gl = kmem_cache_alloc(gfs2_glock_cachep, GFP_KERNEL); | ||
769 | if (!gl) | 771 | if (!gl) |
770 | return -ENOMEM; | 772 | return -ENOMEM; |
771 | 773 | ||
@@ -784,18 +786,18 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
784 | gl->gl_tchange = jiffies; | 786 | gl->gl_tchange = jiffies; |
785 | gl->gl_object = NULL; | 787 | gl->gl_object = NULL; |
786 | gl->gl_sbd = sdp; | 788 | gl->gl_sbd = sdp; |
787 | gl->gl_aspace = NULL; | ||
788 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); | 789 | INIT_DELAYED_WORK(&gl->gl_work, glock_work_func); |
789 | INIT_WORK(&gl->gl_delete, delete_work_func); | 790 | INIT_WORK(&gl->gl_delete, delete_work_func); |
790 | 791 | ||
791 | /* If this glock protects actual on-disk data or metadata blocks, | 792 | mapping = gfs2_glock2aspace(gl); |
792 | create a VFS inode to manage the pages/buffers holding them. */ | 793 | if (mapping) { |
793 | if (glops == &gfs2_inode_glops || glops == &gfs2_rgrp_glops) { | 794 | mapping->a_ops = &gfs2_meta_aops; |
794 | gl->gl_aspace = gfs2_aspace_get(sdp); | 795 | mapping->host = s->s_bdev->bd_inode; |
795 | if (!gl->gl_aspace) { | 796 | mapping->flags = 0; |
796 | error = -ENOMEM; | 797 | mapping_set_gfp_mask(mapping, GFP_NOFS); |
797 | goto fail; | 798 | mapping->assoc_mapping = NULL; |
798 | } | 799 | mapping->backing_dev_info = s->s_bdi; |
800 | mapping->writeback_index = 0; | ||
799 | } | 801 | } |
800 | 802 | ||
801 | write_lock(gl_lock_addr(hash)); | 803 | write_lock(gl_lock_addr(hash)); |
@@ -812,10 +814,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, | |||
812 | *glp = gl; | 814 | *glp = gl; |
813 | 815 | ||
814 | return 0; | 816 | return 0; |
815 | |||
816 | fail: | ||
817 | kmem_cache_free(gfs2_glock_cachep, gl); | ||
818 | return error; | ||
819 | } | 817 | } |
820 | 818 | ||
821 | /** | 819 | /** |
@@ -1510,35 +1508,10 @@ void gfs2_glock_thaw(struct gfs2_sbd *sdp) | |||
1510 | 1508 | ||
1511 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) | 1509 | void gfs2_gl_hash_clear(struct gfs2_sbd *sdp) |
1512 | { | 1510 | { |
1513 | unsigned long t; | ||
1514 | unsigned int x; | 1511 | unsigned int x; |
1515 | int cont; | ||
1516 | 1512 | ||
1517 | t = jiffies; | 1513 | for (x = 0; x < GFS2_GL_HASH_SIZE; x++) |
1518 | 1514 | examine_bucket(clear_glock, sdp, x); | |
1519 | for (;;) { | ||
1520 | cont = 0; | ||
1521 | for (x = 0; x < GFS2_GL_HASH_SIZE; x++) { | ||
1522 | if (examine_bucket(clear_glock, sdp, x)) | ||
1523 | cont = 1; | ||
1524 | } | ||
1525 | |||
1526 | if (!cont) | ||
1527 | break; | ||
1528 | |||
1529 | if (time_after_eq(jiffies, | ||
1530 | t + gfs2_tune_get(sdp, gt_stall_secs) * HZ)) { | ||
1531 | fs_warn(sdp, "Unmount seems to be stalled. " | ||
1532 | "Dumping lock state...\n"); | ||
1533 | gfs2_dump_lockstate(sdp); | ||
1534 | t = jiffies; | ||
1535 | } | ||
1536 | |||
1537 | down_write(&gfs2_umount_flush_sem); | ||
1538 | invalidate_inodes(sdp->sd_vfs); | ||
1539 | up_write(&gfs2_umount_flush_sem); | ||
1540 | msleep(10); | ||
1541 | } | ||
1542 | flush_workqueue(glock_workqueue); | 1515 | flush_workqueue(glock_workqueue); |
1543 | wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0); | 1516 | wait_event(sdp->sd_glock_wait, atomic_read(&sdp->sd_glock_disposal) == 0); |
1544 | gfs2_dump_lockstate(sdp); | 1517 | gfs2_dump_lockstate(sdp); |
@@ -1685,7 +1658,7 @@ static int __dump_glock(struct seq_file *seq, const struct gfs2_glock *gl) | |||
1685 | dtime *= 1000000/HZ; /* demote time in uSec */ | 1658 | dtime *= 1000000/HZ; /* demote time in uSec */ |
1686 | if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) | 1659 | if (!test_bit(GLF_DEMOTE, &gl->gl_flags)) |
1687 | dtime = 0; | 1660 | dtime = 0; |
1688 | gfs2_print_dbg(seq, "G: s:%s n:%u/%llu f:%s t:%s d:%s/%llu a:%d r:%d\n", | 1661 | gfs2_print_dbg(seq, "G: s:%s n:%u/%llx f:%s t:%s d:%s/%llu a:%d r:%d\n", |
1689 | state2str(gl->gl_state), | 1662 | state2str(gl->gl_state), |
1690 | gl->gl_name.ln_type, | 1663 | gl->gl_name.ln_type, |
1691 | (unsigned long long)gl->gl_name.ln_number, | 1664 | (unsigned long long)gl->gl_name.ln_number, |
diff --git a/fs/gfs2/glock.h b/fs/gfs2/glock.h index c0262faf4725..2bda1911b156 100644 --- a/fs/gfs2/glock.h +++ b/fs/gfs2/glock.h | |||
@@ -180,6 +180,13 @@ static inline int gfs2_glock_is_held_shrd(struct gfs2_glock *gl) | |||
180 | return gl->gl_state == LM_ST_SHARED; | 180 | return gl->gl_state == LM_ST_SHARED; |
181 | } | 181 | } |
182 | 182 | ||
183 | static inline struct address_space *gfs2_glock2aspace(struct gfs2_glock *gl) | ||
184 | { | ||
185 | if (gl->gl_ops->go_flags & GLOF_ASPACE) | ||
186 | return (struct address_space *)(gl + 1); | ||
187 | return NULL; | ||
188 | } | ||
189 | |||
183 | int gfs2_glock_get(struct gfs2_sbd *sdp, | 190 | int gfs2_glock_get(struct gfs2_sbd *sdp, |
184 | u64 number, const struct gfs2_glock_operations *glops, | 191 | u64 number, const struct gfs2_glock_operations *glops, |
185 | int create, struct gfs2_glock **glp); | 192 | int create, struct gfs2_glock **glp); |
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 78554acc0605..38e3749d476c 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c | |||
@@ -87,7 +87,7 @@ static void gfs2_ail_empty_gl(struct gfs2_glock *gl) | |||
87 | 87 | ||
88 | static void rgrp_go_sync(struct gfs2_glock *gl) | 88 | static void rgrp_go_sync(struct gfs2_glock *gl) |
89 | { | 89 | { |
90 | struct address_space *metamapping = gl->gl_aspace->i_mapping; | 90 | struct address_space *metamapping = gfs2_glock2aspace(gl); |
91 | int error; | 91 | int error; |
92 | 92 | ||
93 | if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) | 93 | if (!test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) |
@@ -113,7 +113,7 @@ static void rgrp_go_sync(struct gfs2_glock *gl) | |||
113 | 113 | ||
114 | static void rgrp_go_inval(struct gfs2_glock *gl, int flags) | 114 | static void rgrp_go_inval(struct gfs2_glock *gl, int flags) |
115 | { | 115 | { |
116 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 116 | struct address_space *mapping = gfs2_glock2aspace(gl); |
117 | 117 | ||
118 | BUG_ON(!(flags & DIO_METADATA)); | 118 | BUG_ON(!(flags & DIO_METADATA)); |
119 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); | 119 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); |
@@ -134,7 +134,7 @@ static void rgrp_go_inval(struct gfs2_glock *gl, int flags) | |||
134 | static void inode_go_sync(struct gfs2_glock *gl) | 134 | static void inode_go_sync(struct gfs2_glock *gl) |
135 | { | 135 | { |
136 | struct gfs2_inode *ip = gl->gl_object; | 136 | struct gfs2_inode *ip = gl->gl_object; |
137 | struct address_space *metamapping = gl->gl_aspace->i_mapping; | 137 | struct address_space *metamapping = gfs2_glock2aspace(gl); |
138 | int error; | 138 | int error; |
139 | 139 | ||
140 | if (ip && !S_ISREG(ip->i_inode.i_mode)) | 140 | if (ip && !S_ISREG(ip->i_inode.i_mode)) |
@@ -183,7 +183,7 @@ static void inode_go_inval(struct gfs2_glock *gl, int flags) | |||
183 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); | 183 | gfs2_assert_withdraw(gl->gl_sbd, !atomic_read(&gl->gl_ail_count)); |
184 | 184 | ||
185 | if (flags & DIO_METADATA) { | 185 | if (flags & DIO_METADATA) { |
186 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 186 | struct address_space *mapping = gfs2_glock2aspace(gl); |
187 | truncate_inode_pages(mapping, 0); | 187 | truncate_inode_pages(mapping, 0); |
188 | if (ip) { | 188 | if (ip) { |
189 | set_bit(GIF_INVALID, &ip->i_flags); | 189 | set_bit(GIF_INVALID, &ip->i_flags); |
@@ -282,7 +282,8 @@ static int inode_go_dump(struct seq_file *seq, const struct gfs2_glock *gl) | |||
282 | 282 | ||
283 | static int rgrp_go_demote_ok(const struct gfs2_glock *gl) | 283 | static int rgrp_go_demote_ok(const struct gfs2_glock *gl) |
284 | { | 284 | { |
285 | return !gl->gl_aspace->i_mapping->nrpages; | 285 | const struct address_space *mapping = (const struct address_space *)(gl + 1); |
286 | return !mapping->nrpages; | ||
286 | } | 287 | } |
287 | 288 | ||
288 | /** | 289 | /** |
@@ -387,8 +388,7 @@ static void iopen_go_callback(struct gfs2_glock *gl) | |||
387 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; | 388 | struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; |
388 | 389 | ||
389 | if (gl->gl_demote_state == LM_ST_UNLOCKED && | 390 | if (gl->gl_demote_state == LM_ST_UNLOCKED && |
390 | gl->gl_state == LM_ST_SHARED && | 391 | gl->gl_state == LM_ST_SHARED && ip) { |
391 | ip && test_bit(GIF_USER, &ip->i_flags)) { | ||
392 | gfs2_glock_hold(gl); | 392 | gfs2_glock_hold(gl); |
393 | if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) | 393 | if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) |
394 | gfs2_glock_put_nolock(gl); | 394 | gfs2_glock_put_nolock(gl); |
@@ -407,6 +407,7 @@ const struct gfs2_glock_operations gfs2_inode_glops = { | |||
407 | .go_dump = inode_go_dump, | 407 | .go_dump = inode_go_dump, |
408 | .go_type = LM_TYPE_INODE, | 408 | .go_type = LM_TYPE_INODE, |
409 | .go_min_hold_time = HZ / 5, | 409 | .go_min_hold_time = HZ / 5, |
410 | .go_flags = GLOF_ASPACE, | ||
410 | }; | 411 | }; |
411 | 412 | ||
412 | const struct gfs2_glock_operations gfs2_rgrp_glops = { | 413 | const struct gfs2_glock_operations gfs2_rgrp_glops = { |
@@ -418,6 +419,7 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = { | |||
418 | .go_dump = gfs2_rgrp_dump, | 419 | .go_dump = gfs2_rgrp_dump, |
419 | .go_type = LM_TYPE_RGRP, | 420 | .go_type = LM_TYPE_RGRP, |
420 | .go_min_hold_time = HZ / 5, | 421 | .go_min_hold_time = HZ / 5, |
422 | .go_flags = GLOF_ASPACE, | ||
421 | }; | 423 | }; |
422 | 424 | ||
423 | const struct gfs2_glock_operations gfs2_trans_glops = { | 425 | const struct gfs2_glock_operations gfs2_trans_glops = { |
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index bc0ad158e6b4..b8025e51cabf 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h | |||
@@ -162,6 +162,8 @@ struct gfs2_glock_operations { | |||
162 | void (*go_callback) (struct gfs2_glock *gl); | 162 | void (*go_callback) (struct gfs2_glock *gl); |
163 | const int go_type; | 163 | const int go_type; |
164 | const unsigned long go_min_hold_time; | 164 | const unsigned long go_min_hold_time; |
165 | const unsigned long go_flags; | ||
166 | #define GLOF_ASPACE 1 | ||
165 | }; | 167 | }; |
166 | 168 | ||
167 | enum { | 169 | enum { |
@@ -225,7 +227,6 @@ struct gfs2_glock { | |||
225 | 227 | ||
226 | struct gfs2_sbd *gl_sbd; | 228 | struct gfs2_sbd *gl_sbd; |
227 | 229 | ||
228 | struct inode *gl_aspace; | ||
229 | struct list_head gl_ail_list; | 230 | struct list_head gl_ail_list; |
230 | atomic_t gl_ail_count; | 231 | atomic_t gl_ail_count; |
231 | struct delayed_work gl_work; | 232 | struct delayed_work gl_work; |
@@ -258,7 +259,6 @@ enum { | |||
258 | GIF_INVALID = 0, | 259 | GIF_INVALID = 0, |
259 | GIF_QD_LOCKED = 1, | 260 | GIF_QD_LOCKED = 1, |
260 | GIF_SW_PAGED = 3, | 261 | GIF_SW_PAGED = 3, |
261 | GIF_USER = 4, /* user inode, not metadata addr space */ | ||
262 | }; | 262 | }; |
263 | 263 | ||
264 | 264 | ||
@@ -451,7 +451,6 @@ struct gfs2_tune { | |||
451 | unsigned int gt_quota_quantum; /* Secs between syncs to quota file */ | 451 | unsigned int gt_quota_quantum; /* Secs between syncs to quota file */ |
452 | unsigned int gt_new_files_jdata; | 452 | unsigned int gt_new_files_jdata; |
453 | unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ | 453 | unsigned int gt_max_readahead; /* Max bytes to read-ahead from disk */ |
454 | unsigned int gt_stall_secs; /* Detects trouble! */ | ||
455 | unsigned int gt_complain_secs; | 454 | unsigned int gt_complain_secs; |
456 | unsigned int gt_statfs_quantum; | 455 | unsigned int gt_statfs_quantum; |
457 | unsigned int gt_statfs_slow; | 456 | unsigned int gt_statfs_slow; |
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 6e220f4eee7d..b1bf2694fb2b 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c | |||
@@ -45,7 +45,7 @@ static int iget_test(struct inode *inode, void *opaque) | |||
45 | struct gfs2_inode *ip = GFS2_I(inode); | 45 | struct gfs2_inode *ip = GFS2_I(inode); |
46 | u64 *no_addr = opaque; | 46 | u64 *no_addr = opaque; |
47 | 47 | ||
48 | if (ip->i_no_addr == *no_addr && test_bit(GIF_USER, &ip->i_flags)) | 48 | if (ip->i_no_addr == *no_addr) |
49 | return 1; | 49 | return 1; |
50 | 50 | ||
51 | return 0; | 51 | return 0; |
@@ -58,7 +58,6 @@ static int iget_set(struct inode *inode, void *opaque) | |||
58 | 58 | ||
59 | inode->i_ino = (unsigned long)*no_addr; | 59 | inode->i_ino = (unsigned long)*no_addr; |
60 | ip->i_no_addr = *no_addr; | 60 | ip->i_no_addr = *no_addr; |
61 | set_bit(GIF_USER, &ip->i_flags); | ||
62 | return 0; | 61 | return 0; |
63 | } | 62 | } |
64 | 63 | ||
@@ -84,7 +83,7 @@ static int iget_skip_test(struct inode *inode, void *opaque) | |||
84 | struct gfs2_inode *ip = GFS2_I(inode); | 83 | struct gfs2_inode *ip = GFS2_I(inode); |
85 | struct gfs2_skip_data *data = opaque; | 84 | struct gfs2_skip_data *data = opaque; |
86 | 85 | ||
87 | if (ip->i_no_addr == data->no_addr && test_bit(GIF_USER, &ip->i_flags)){ | 86 | if (ip->i_no_addr == data->no_addr) { |
88 | if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ | 87 | if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)){ |
89 | data->skipped = 1; | 88 | data->skipped = 1; |
90 | return 0; | 89 | return 0; |
@@ -103,7 +102,6 @@ static int iget_skip_set(struct inode *inode, void *opaque) | |||
103 | return 1; | 102 | return 1; |
104 | inode->i_ino = (unsigned long)(data->no_addr); | 103 | inode->i_ino = (unsigned long)(data->no_addr); |
105 | ip->i_no_addr = data->no_addr; | 104 | ip->i_no_addr = data->no_addr; |
106 | set_bit(GIF_USER, &ip->i_flags); | ||
107 | return 0; | 105 | return 0; |
108 | } | 106 | } |
109 | 107 | ||
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index 0e5e0e7022e5..569b46240f61 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c | |||
@@ -30,7 +30,10 @@ static void gdlm_ast(void *arg) | |||
30 | 30 | ||
31 | switch (gl->gl_lksb.sb_status) { | 31 | switch (gl->gl_lksb.sb_status) { |
32 | case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ | 32 | case -DLM_EUNLOCK: /* Unlocked, so glock can be freed */ |
33 | kmem_cache_free(gfs2_glock_cachep, gl); | 33 | if (gl->gl_ops->go_flags & GLOF_ASPACE) |
34 | kmem_cache_free(gfs2_glock_aspace_cachep, gl); | ||
35 | else | ||
36 | kmem_cache_free(gfs2_glock_cachep, gl); | ||
34 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) | 37 | if (atomic_dec_and_test(&sdp->sd_glock_disposal)) |
35 | wake_up(&sdp->sd_glock_wait); | 38 | wake_up(&sdp->sd_glock_wait); |
36 | return; | 39 | return; |
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index de97632ba32f..adc260fbea90 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
@@ -528,9 +528,9 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) | |||
528 | gfs2_pin(sdp, bd->bd_bh); | 528 | gfs2_pin(sdp, bd->bd_bh); |
529 | tr->tr_num_databuf_new++; | 529 | tr->tr_num_databuf_new++; |
530 | sdp->sd_log_num_databuf++; | 530 | sdp->sd_log_num_databuf++; |
531 | list_add(&le->le_list, &sdp->sd_log_le_databuf); | 531 | list_add_tail(&le->le_list, &sdp->sd_log_le_databuf); |
532 | } else { | 532 | } else { |
533 | list_add(&le->le_list, &sdp->sd_log_le_ordered); | 533 | list_add_tail(&le->le_list, &sdp->sd_log_le_ordered); |
534 | } | 534 | } |
535 | out: | 535 | out: |
536 | gfs2_log_unlock(sdp); | 536 | gfs2_log_unlock(sdp); |
diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index 5b31f7741a8f..a88fadc704bb 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c | |||
@@ -52,6 +52,22 @@ static void gfs2_init_glock_once(void *foo) | |||
52 | atomic_set(&gl->gl_ail_count, 0); | 52 | atomic_set(&gl->gl_ail_count, 0); |
53 | } | 53 | } |
54 | 54 | ||
55 | static void gfs2_init_gl_aspace_once(void *foo) | ||
56 | { | ||
57 | struct gfs2_glock *gl = foo; | ||
58 | struct address_space *mapping = (struct address_space *)(gl + 1); | ||
59 | |||
60 | gfs2_init_glock_once(gl); | ||
61 | memset(mapping, 0, sizeof(*mapping)); | ||
62 | INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC); | ||
63 | spin_lock_init(&mapping->tree_lock); | ||
64 | spin_lock_init(&mapping->i_mmap_lock); | ||
65 | INIT_LIST_HEAD(&mapping->private_list); | ||
66 | spin_lock_init(&mapping->private_lock); | ||
67 | INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap); | ||
68 | INIT_LIST_HEAD(&mapping->i_mmap_nonlinear); | ||
69 | } | ||
70 | |||
55 | /** | 71 | /** |
56 | * init_gfs2_fs - Register GFS2 as a filesystem | 72 | * init_gfs2_fs - Register GFS2 as a filesystem |
57 | * | 73 | * |
@@ -78,6 +94,14 @@ static int __init init_gfs2_fs(void) | |||
78 | if (!gfs2_glock_cachep) | 94 | if (!gfs2_glock_cachep) |
79 | goto fail; | 95 | goto fail; |
80 | 96 | ||
97 | gfs2_glock_aspace_cachep = kmem_cache_create("gfs2_glock (aspace)", | ||
98 | sizeof(struct gfs2_glock) + | ||
99 | sizeof(struct address_space), | ||
100 | 0, 0, gfs2_init_gl_aspace_once); | ||
101 | |||
102 | if (!gfs2_glock_aspace_cachep) | ||
103 | goto fail; | ||
104 | |||
81 | gfs2_inode_cachep = kmem_cache_create("gfs2_inode", | 105 | gfs2_inode_cachep = kmem_cache_create("gfs2_inode", |
82 | sizeof(struct gfs2_inode), | 106 | sizeof(struct gfs2_inode), |
83 | 0, SLAB_RECLAIM_ACCOUNT| | 107 | 0, SLAB_RECLAIM_ACCOUNT| |
@@ -144,6 +168,9 @@ fail: | |||
144 | if (gfs2_inode_cachep) | 168 | if (gfs2_inode_cachep) |
145 | kmem_cache_destroy(gfs2_inode_cachep); | 169 | kmem_cache_destroy(gfs2_inode_cachep); |
146 | 170 | ||
171 | if (gfs2_glock_aspace_cachep) | ||
172 | kmem_cache_destroy(gfs2_glock_aspace_cachep); | ||
173 | |||
147 | if (gfs2_glock_cachep) | 174 | if (gfs2_glock_cachep) |
148 | kmem_cache_destroy(gfs2_glock_cachep); | 175 | kmem_cache_destroy(gfs2_glock_cachep); |
149 | 176 | ||
@@ -169,6 +196,7 @@ static void __exit exit_gfs2_fs(void) | |||
169 | kmem_cache_destroy(gfs2_rgrpd_cachep); | 196 | kmem_cache_destroy(gfs2_rgrpd_cachep); |
170 | kmem_cache_destroy(gfs2_bufdata_cachep); | 197 | kmem_cache_destroy(gfs2_bufdata_cachep); |
171 | kmem_cache_destroy(gfs2_inode_cachep); | 198 | kmem_cache_destroy(gfs2_inode_cachep); |
199 | kmem_cache_destroy(gfs2_glock_aspace_cachep); | ||
172 | kmem_cache_destroy(gfs2_glock_cachep); | 200 | kmem_cache_destroy(gfs2_glock_cachep); |
173 | 201 | ||
174 | gfs2_sys_uninit(); | 202 | gfs2_sys_uninit(); |
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 6f68a5f18eb8..0bb12c80937a 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c | |||
@@ -93,49 +93,13 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb | |||
93 | return err; | 93 | return err; |
94 | } | 94 | } |
95 | 95 | ||
96 | static const struct address_space_operations aspace_aops = { | 96 | const struct address_space_operations gfs2_meta_aops = { |
97 | .writepage = gfs2_aspace_writepage, | 97 | .writepage = gfs2_aspace_writepage, |
98 | .releasepage = gfs2_releasepage, | 98 | .releasepage = gfs2_releasepage, |
99 | .sync_page = block_sync_page, | 99 | .sync_page = block_sync_page, |
100 | }; | 100 | }; |
101 | 101 | ||
102 | /** | 102 | /** |
103 | * gfs2_aspace_get - Create and initialize a struct inode structure | ||
104 | * @sdp: the filesystem the aspace is in | ||
105 | * | ||
106 | * Right now a struct inode is just a struct inode. Maybe Linux | ||
107 | * will supply a more lightweight address space construct (that works) | ||
108 | * in the future. | ||
109 | * | ||
110 | * Make sure pages/buffers in this aspace aren't in high memory. | ||
111 | * | ||
112 | * Returns: the aspace | ||
113 | */ | ||
114 | |||
115 | struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp) | ||
116 | { | ||
117 | struct inode *aspace; | ||
118 | struct gfs2_inode *ip; | ||
119 | |||
120 | aspace = new_inode(sdp->sd_vfs); | ||
121 | if (aspace) { | ||
122 | mapping_set_gfp_mask(aspace->i_mapping, GFP_NOFS); | ||
123 | aspace->i_mapping->a_ops = &aspace_aops; | ||
124 | aspace->i_size = MAX_LFS_FILESIZE; | ||
125 | ip = GFS2_I(aspace); | ||
126 | clear_bit(GIF_USER, &ip->i_flags); | ||
127 | insert_inode_hash(aspace); | ||
128 | } | ||
129 | return aspace; | ||
130 | } | ||
131 | |||
132 | void gfs2_aspace_put(struct inode *aspace) | ||
133 | { | ||
134 | remove_inode_hash(aspace); | ||
135 | iput(aspace); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * gfs2_meta_sync - Sync all buffers associated with a glock | 103 | * gfs2_meta_sync - Sync all buffers associated with a glock |
140 | * @gl: The glock | 104 | * @gl: The glock |
141 | * | 105 | * |
@@ -143,7 +107,7 @@ void gfs2_aspace_put(struct inode *aspace) | |||
143 | 107 | ||
144 | void gfs2_meta_sync(struct gfs2_glock *gl) | 108 | void gfs2_meta_sync(struct gfs2_glock *gl) |
145 | { | 109 | { |
146 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 110 | struct address_space *mapping = gfs2_glock2aspace(gl); |
147 | int error; | 111 | int error; |
148 | 112 | ||
149 | filemap_fdatawrite(mapping); | 113 | filemap_fdatawrite(mapping); |
@@ -164,7 +128,7 @@ void gfs2_meta_sync(struct gfs2_glock *gl) | |||
164 | 128 | ||
165 | struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) | 129 | struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create) |
166 | { | 130 | { |
167 | struct address_space *mapping = gl->gl_aspace->i_mapping; | 131 | struct address_space *mapping = gfs2_glock2aspace(gl); |
168 | struct gfs2_sbd *sdp = gl->gl_sbd; | 132 | struct gfs2_sbd *sdp = gl->gl_sbd; |
169 | struct page *page; | 133 | struct page *page; |
170 | struct buffer_head *bh; | 134 | struct buffer_head *bh; |
@@ -344,8 +308,10 @@ void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, | |||
344 | 308 | ||
345 | void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta) | 309 | void gfs2_remove_from_journal(struct buffer_head *bh, struct gfs2_trans *tr, int meta) |
346 | { | 310 | { |
347 | struct gfs2_sbd *sdp = GFS2_SB(bh->b_page->mapping->host); | 311 | struct address_space *mapping = bh->b_page->mapping; |
312 | struct gfs2_sbd *sdp = gfs2_mapping2sbd(mapping); | ||
348 | struct gfs2_bufdata *bd = bh->b_private; | 313 | struct gfs2_bufdata *bd = bh->b_private; |
314 | |||
349 | if (test_clear_buffer_pinned(bh)) { | 315 | if (test_clear_buffer_pinned(bh)) { |
350 | list_del_init(&bd->bd_le.le_list); | 316 | list_del_init(&bd->bd_le.le_list); |
351 | if (meta) { | 317 | if (meta) { |
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h index de270c2f9b63..6a1d9ba16411 100644 --- a/fs/gfs2/meta_io.h +++ b/fs/gfs2/meta_io.h | |||
@@ -37,8 +37,16 @@ static inline void gfs2_buffer_copy_tail(struct buffer_head *to_bh, | |||
37 | 0, from_head - to_head); | 37 | 0, from_head - to_head); |
38 | } | 38 | } |
39 | 39 | ||
40 | struct inode *gfs2_aspace_get(struct gfs2_sbd *sdp); | 40 | extern const struct address_space_operations gfs2_meta_aops; |
41 | void gfs2_aspace_put(struct inode *aspace); | 41 | |
42 | static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping) | ||
43 | { | ||
44 | struct inode *inode = mapping->host; | ||
45 | if (mapping->a_ops == &gfs2_meta_aops) | ||
46 | return (((struct gfs2_glock *)mapping) - 1)->gl_sbd; | ||
47 | else | ||
48 | return inode->i_sb->s_fs_info; | ||
49 | } | ||
42 | 50 | ||
43 | void gfs2_meta_sync(struct gfs2_glock *gl); | 51 | void gfs2_meta_sync(struct gfs2_glock *gl); |
44 | 52 | ||
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index a86ed6381566..a054b526dc08 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c | |||
@@ -65,7 +65,6 @@ static void gfs2_tune_init(struct gfs2_tune *gt) | |||
65 | gt->gt_quota_scale_den = 1; | 65 | gt->gt_quota_scale_den = 1; |
66 | gt->gt_new_files_jdata = 0; | 66 | gt->gt_new_files_jdata = 0; |
67 | gt->gt_max_readahead = 1 << 18; | 67 | gt->gt_max_readahead = 1 << 18; |
68 | gt->gt_stall_secs = 600; | ||
69 | gt->gt_complain_secs = 10; | 68 | gt->gt_complain_secs = 10; |
70 | } | 69 | } |
71 | 70 | ||
@@ -1241,10 +1240,9 @@ fail_sb: | |||
1241 | fail_locking: | 1240 | fail_locking: |
1242 | init_locking(sdp, &mount_gh, UNDO); | 1241 | init_locking(sdp, &mount_gh, UNDO); |
1243 | fail_lm: | 1242 | fail_lm: |
1243 | invalidate_inodes(sb); | ||
1244 | gfs2_gl_hash_clear(sdp); | 1244 | gfs2_gl_hash_clear(sdp); |
1245 | gfs2_lm_unmount(sdp); | 1245 | gfs2_lm_unmount(sdp); |
1246 | while (invalidate_inodes(sb)) | ||
1247 | yield(); | ||
1248 | fail_sys: | 1246 | fail_sys: |
1249 | gfs2_sys_fs_del(sdp); | 1247 | gfs2_sys_fs_del(sdp); |
1250 | fail: | 1248 | fail: |
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index b9dd3da22c0a..e5e22629da67 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
@@ -722,8 +722,7 @@ static int gfs2_write_inode(struct inode *inode, int sync) | |||
722 | int ret = 0; | 722 | int ret = 0; |
723 | 723 | ||
724 | /* Check this is a "normal" inode, etc */ | 724 | /* Check this is a "normal" inode, etc */ |
725 | if (!test_bit(GIF_USER, &ip->i_flags) || | 725 | if (current->flags & PF_MEMALLOC) |
726 | (current->flags & PF_MEMALLOC)) | ||
727 | return 0; | 726 | return 0; |
728 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 727 | ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
729 | if (ret) | 728 | if (ret) |
@@ -860,6 +859,7 @@ restart: | |||
860 | gfs2_clear_rgrpd(sdp); | 859 | gfs2_clear_rgrpd(sdp); |
861 | gfs2_jindex_free(sdp); | 860 | gfs2_jindex_free(sdp); |
862 | /* Take apart glock structures and buffer lists */ | 861 | /* Take apart glock structures and buffer lists */ |
862 | invalidate_inodes(sdp->sd_vfs); | ||
863 | gfs2_gl_hash_clear(sdp); | 863 | gfs2_gl_hash_clear(sdp); |
864 | /* Unmount the locking protocol */ | 864 | /* Unmount the locking protocol */ |
865 | gfs2_lm_unmount(sdp); | 865 | gfs2_lm_unmount(sdp); |
@@ -1194,7 +1194,7 @@ static void gfs2_drop_inode(struct inode *inode) | |||
1194 | { | 1194 | { |
1195 | struct gfs2_inode *ip = GFS2_I(inode); | 1195 | struct gfs2_inode *ip = GFS2_I(inode); |
1196 | 1196 | ||
1197 | if (test_bit(GIF_USER, &ip->i_flags) && inode->i_nlink) { | 1197 | if (inode->i_nlink) { |
1198 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; | 1198 | struct gfs2_glock *gl = ip->i_iopen_gh.gh_gl; |
1199 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) | 1199 | if (gl && test_bit(GLF_DEMOTE, &gl->gl_flags)) |
1200 | clear_nlink(inode); | 1200 | clear_nlink(inode); |
@@ -1212,18 +1212,12 @@ static void gfs2_clear_inode(struct inode *inode) | |||
1212 | { | 1212 | { |
1213 | struct gfs2_inode *ip = GFS2_I(inode); | 1213 | struct gfs2_inode *ip = GFS2_I(inode); |
1214 | 1214 | ||
1215 | /* This tells us its a "real" inode and not one which only | 1215 | ip->i_gl->gl_object = NULL; |
1216 | * serves to contain an address space (see rgrp.c, meta_io.c) | 1216 | gfs2_glock_put(ip->i_gl); |
1217 | * which therefore doesn't have its own glocks. | 1217 | ip->i_gl = NULL; |
1218 | */ | 1218 | if (ip->i_iopen_gh.gh_gl) { |
1219 | if (test_bit(GIF_USER, &ip->i_flags)) { | 1219 | ip->i_iopen_gh.gh_gl->gl_object = NULL; |
1220 | ip->i_gl->gl_object = NULL; | 1220 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
1221 | gfs2_glock_put(ip->i_gl); | ||
1222 | ip->i_gl = NULL; | ||
1223 | if (ip->i_iopen_gh.gh_gl) { | ||
1224 | ip->i_iopen_gh.gh_gl->gl_object = NULL; | ||
1225 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | ||
1226 | } | ||
1227 | } | 1221 | } |
1228 | } | 1222 | } |
1229 | 1223 | ||
@@ -1358,9 +1352,6 @@ static void gfs2_delete_inode(struct inode *inode) | |||
1358 | struct gfs2_holder gh; | 1352 | struct gfs2_holder gh; |
1359 | int error; | 1353 | int error; |
1360 | 1354 | ||
1361 | if (!test_bit(GIF_USER, &ip->i_flags)) | ||
1362 | goto out; | ||
1363 | |||
1364 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); | 1355 | error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); |
1365 | if (unlikely(error)) { | 1356 | if (unlikely(error)) { |
1366 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); | 1357 | gfs2_glock_dq_uninit(&ip->i_iopen_gh); |
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 0dc34621f6a6..a0db1c94317d 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c | |||
@@ -478,7 +478,6 @@ TUNE_ATTR(complain_secs, 0); | |||
478 | TUNE_ATTR(statfs_slow, 0); | 478 | TUNE_ATTR(statfs_slow, 0); |
479 | TUNE_ATTR(new_files_jdata, 0); | 479 | TUNE_ATTR(new_files_jdata, 0); |
480 | TUNE_ATTR(quota_simul_sync, 1); | 480 | TUNE_ATTR(quota_simul_sync, 1); |
481 | TUNE_ATTR(stall_secs, 1); | ||
482 | TUNE_ATTR(statfs_quantum, 1); | 481 | TUNE_ATTR(statfs_quantum, 1); |
483 | TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store); | 482 | TUNE_ATTR_3(quota_scale, quota_scale_show, quota_scale_store); |
484 | 483 | ||
@@ -491,7 +490,6 @@ static struct attribute *tune_attrs[] = { | |||
491 | &tune_attr_complain_secs.attr, | 490 | &tune_attr_complain_secs.attr, |
492 | &tune_attr_statfs_slow.attr, | 491 | &tune_attr_statfs_slow.attr, |
493 | &tune_attr_quota_simul_sync.attr, | 492 | &tune_attr_quota_simul_sync.attr, |
494 | &tune_attr_stall_secs.attr, | ||
495 | &tune_attr_statfs_quantum.attr, | 493 | &tune_attr_statfs_quantum.attr, |
496 | &tune_attr_quota_scale.attr, | 494 | &tune_attr_quota_scale.attr, |
497 | &tune_attr_new_files_jdata.attr, | 495 | &tune_attr_new_files_jdata.attr, |
diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index f6a7efa34eb9..226f2bfbf16a 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "util.h" | 21 | #include "util.h" |
22 | 22 | ||
23 | struct kmem_cache *gfs2_glock_cachep __read_mostly; | 23 | struct kmem_cache *gfs2_glock_cachep __read_mostly; |
24 | struct kmem_cache *gfs2_glock_aspace_cachep __read_mostly; | ||
24 | struct kmem_cache *gfs2_inode_cachep __read_mostly; | 25 | struct kmem_cache *gfs2_inode_cachep __read_mostly; |
25 | struct kmem_cache *gfs2_bufdata_cachep __read_mostly; | 26 | struct kmem_cache *gfs2_bufdata_cachep __read_mostly; |
26 | struct kmem_cache *gfs2_rgrpd_cachep __read_mostly; | 27 | struct kmem_cache *gfs2_rgrpd_cachep __read_mostly; |
diff --git a/fs/gfs2/util.h b/fs/gfs2/util.h index 33e96b0ce9ab..b432e04600de 100644 --- a/fs/gfs2/util.h +++ b/fs/gfs2/util.h | |||
@@ -145,6 +145,7 @@ gfs2_io_error_bh_i((sdp), (bh), __func__, __FILE__, __LINE__); | |||
145 | 145 | ||
146 | 146 | ||
147 | extern struct kmem_cache *gfs2_glock_cachep; | 147 | extern struct kmem_cache *gfs2_glock_cachep; |
148 | extern struct kmem_cache *gfs2_glock_aspace_cachep; | ||
148 | extern struct kmem_cache *gfs2_inode_cachep; | 149 | extern struct kmem_cache *gfs2_inode_cachep; |
149 | extern struct kmem_cache *gfs2_bufdata_cachep; | 150 | extern struct kmem_cache *gfs2_bufdata_cachep; |
150 | extern struct kmem_cache *gfs2_rgrpd_cachep; | 151 | extern struct kmem_cache *gfs2_rgrpd_cachep; |
diff --git a/fs/nfs/iostat.h b/fs/nfs/iostat.h index 46d779abafd3..1d8d5c813b01 100644 --- a/fs/nfs/iostat.h +++ b/fs/nfs/iostat.h | |||
@@ -57,12 +57,12 @@ static inline void nfs_add_fscache_stats(struct inode *inode, | |||
57 | } | 57 | } |
58 | #endif | 58 | #endif |
59 | 59 | ||
60 | static inline struct nfs_iostats *nfs_alloc_iostats(void) | 60 | static inline struct nfs_iostats __percpu *nfs_alloc_iostats(void) |
61 | { | 61 | { |
62 | return alloc_percpu(struct nfs_iostats); | 62 | return alloc_percpu(struct nfs_iostats); |
63 | } | 63 | } |
64 | 64 | ||
65 | static inline void nfs_free_iostats(struct nfs_iostats *stats) | 65 | static inline void nfs_free_iostats(struct nfs_iostats __percpu *stats) |
66 | { | 66 | { |
67 | if (stats != NULL) | 67 | if (stats != NULL) |
68 | free_percpu(stats); | 68 | free_percpu(stats); |
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index 7ca78346d3f0..cfe90a48a6e8 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c | |||
@@ -12,37 +12,37 @@ | |||
12 | #include <linux/poll.h> | 12 | #include <linux/poll.h> |
13 | #include <linux/proc_fs.h> | 13 | #include <linux/proc_fs.h> |
14 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
15 | #include <linux/syslog.h> | ||
15 | 16 | ||
16 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
17 | #include <asm/io.h> | 18 | #include <asm/io.h> |
18 | 19 | ||
19 | extern wait_queue_head_t log_wait; | 20 | extern wait_queue_head_t log_wait; |
20 | 21 | ||
21 | extern int do_syslog(int type, char __user *bug, int count); | ||
22 | |||
23 | static int kmsg_open(struct inode * inode, struct file * file) | 22 | static int kmsg_open(struct inode * inode, struct file * file) |
24 | { | 23 | { |
25 | return do_syslog(1,NULL,0); | 24 | return do_syslog(SYSLOG_ACTION_OPEN, NULL, 0, SYSLOG_FROM_FILE); |
26 | } | 25 | } |
27 | 26 | ||
28 | static int kmsg_release(struct inode * inode, struct file * file) | 27 | static int kmsg_release(struct inode * inode, struct file * file) |
29 | { | 28 | { |
30 | (void) do_syslog(0,NULL,0); | 29 | (void) do_syslog(SYSLOG_ACTION_CLOSE, NULL, 0, SYSLOG_FROM_FILE); |
31 | return 0; | 30 | return 0; |
32 | } | 31 | } |
33 | 32 | ||
34 | static ssize_t kmsg_read(struct file *file, char __user *buf, | 33 | static ssize_t kmsg_read(struct file *file, char __user *buf, |
35 | size_t count, loff_t *ppos) | 34 | size_t count, loff_t *ppos) |
36 | { | 35 | { |
37 | if ((file->f_flags & O_NONBLOCK) && !do_syslog(9, NULL, 0)) | 36 | if ((file->f_flags & O_NONBLOCK) && |
37 | !do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE)) | ||
38 | return -EAGAIN; | 38 | return -EAGAIN; |
39 | return do_syslog(2, buf, count); | 39 | return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_FILE); |
40 | } | 40 | } |
41 | 41 | ||
42 | static unsigned int kmsg_poll(struct file *file, poll_table *wait) | 42 | static unsigned int kmsg_poll(struct file *file, poll_table *wait) |
43 | { | 43 | { |
44 | poll_wait(file, &log_wait, wait); | 44 | poll_wait(file, &log_wait, wait); |
45 | if (do_syslog(9, NULL, 0)) | 45 | if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_FILE)) |
46 | return POLLIN | POLLRDNORM; | 46 | return POLLIN | POLLRDNORM; |
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
diff --git a/fs/seq_file.c b/fs/seq_file.c index eae7d9dbf3ff..5afd554efad3 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
@@ -674,7 +674,6 @@ struct list_head *seq_list_start(struct list_head *head, loff_t pos) | |||
674 | 674 | ||
675 | return NULL; | 675 | return NULL; |
676 | } | 676 | } |
677 | |||
678 | EXPORT_SYMBOL(seq_list_start); | 677 | EXPORT_SYMBOL(seq_list_start); |
679 | 678 | ||
680 | struct list_head *seq_list_start_head(struct list_head *head, loff_t pos) | 679 | struct list_head *seq_list_start_head(struct list_head *head, loff_t pos) |
@@ -684,7 +683,6 @@ struct list_head *seq_list_start_head(struct list_head *head, loff_t pos) | |||
684 | 683 | ||
685 | return seq_list_start(head, pos - 1); | 684 | return seq_list_start(head, pos - 1); |
686 | } | 685 | } |
687 | |||
688 | EXPORT_SYMBOL(seq_list_start_head); | 686 | EXPORT_SYMBOL(seq_list_start_head); |
689 | 687 | ||
690 | struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos) | 688 | struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos) |
@@ -695,5 +693,131 @@ struct list_head *seq_list_next(void *v, struct list_head *head, loff_t *ppos) | |||
695 | ++*ppos; | 693 | ++*ppos; |
696 | return lh == head ? NULL : lh; | 694 | return lh == head ? NULL : lh; |
697 | } | 695 | } |
698 | |||
699 | EXPORT_SYMBOL(seq_list_next); | 696 | EXPORT_SYMBOL(seq_list_next); |
697 | |||
698 | /** | ||
699 | * seq_hlist_start - start an iteration of a hlist | ||
700 | * @head: the head of the hlist | ||
701 | * @pos: the start position of the sequence | ||
702 | * | ||
703 | * Called at seq_file->op->start(). | ||
704 | */ | ||
705 | struct hlist_node *seq_hlist_start(struct hlist_head *head, loff_t pos) | ||
706 | { | ||
707 | struct hlist_node *node; | ||
708 | |||
709 | hlist_for_each(node, head) | ||
710 | if (pos-- == 0) | ||
711 | return node; | ||
712 | return NULL; | ||
713 | } | ||
714 | EXPORT_SYMBOL(seq_hlist_start); | ||
715 | |||
716 | /** | ||
717 | * seq_hlist_start_head - start an iteration of a hlist | ||
718 | * @head: the head of the hlist | ||
719 | * @pos: the start position of the sequence | ||
720 | * | ||
721 | * Called at seq_file->op->start(). Call this function if you want to | ||
722 | * print a header at the top of the output. | ||
723 | */ | ||
724 | struct hlist_node *seq_hlist_start_head(struct hlist_head *head, loff_t pos) | ||
725 | { | ||
726 | if (!pos) | ||
727 | return SEQ_START_TOKEN; | ||
728 | |||
729 | return seq_hlist_start(head, pos - 1); | ||
730 | } | ||
731 | EXPORT_SYMBOL(seq_hlist_start_head); | ||
732 | |||
733 | /** | ||
734 | * seq_hlist_next - move to the next position of the hlist | ||
735 | * @v: the current iterator | ||
736 | * @head: the head of the hlist | ||
737 | * @pos: the current posision | ||
738 | * | ||
739 | * Called at seq_file->op->next(). | ||
740 | */ | ||
741 | struct hlist_node *seq_hlist_next(void *v, struct hlist_head *head, | ||
742 | loff_t *ppos) | ||
743 | { | ||
744 | struct hlist_node *node = v; | ||
745 | |||
746 | ++*ppos; | ||
747 | if (v == SEQ_START_TOKEN) | ||
748 | return head->first; | ||
749 | else | ||
750 | return node->next; | ||
751 | } | ||
752 | EXPORT_SYMBOL(seq_hlist_next); | ||
753 | |||
754 | /** | ||
755 | * seq_hlist_start_rcu - start an iteration of a hlist protected by RCU | ||
756 | * @head: the head of the hlist | ||
757 | * @pos: the start position of the sequence | ||
758 | * | ||
759 | * Called at seq_file->op->start(). | ||
760 | * | ||
761 | * This list-traversal primitive may safely run concurrently with | ||
762 | * the _rcu list-mutation primitives such as hlist_add_head_rcu() | ||
763 | * as long as the traversal is guarded by rcu_read_lock(). | ||
764 | */ | ||
765 | struct hlist_node *seq_hlist_start_rcu(struct hlist_head *head, | ||
766 | loff_t pos) | ||
767 | { | ||
768 | struct hlist_node *node; | ||
769 | |||
770 | __hlist_for_each_rcu(node, head) | ||
771 | if (pos-- == 0) | ||
772 | return node; | ||
773 | return NULL; | ||
774 | } | ||
775 | EXPORT_SYMBOL(seq_hlist_start_rcu); | ||
776 | |||
777 | /** | ||
778 | * seq_hlist_start_head_rcu - start an iteration of a hlist protected by RCU | ||
779 | * @head: the head of the hlist | ||
780 | * @pos: the start position of the sequence | ||
781 | * | ||
782 | * Called at seq_file->op->start(). Call this function if you want to | ||
783 | * print a header at the top of the output. | ||
784 | * | ||
785 | * This list-traversal primitive may safely run concurrently with | ||
786 | * the _rcu list-mutation primitives such as hlist_add_head_rcu() | ||
787 | * as long as the traversal is guarded by rcu_read_lock(). | ||
788 | */ | ||
789 | struct hlist_node *seq_hlist_start_head_rcu(struct hlist_head *head, | ||
790 | loff_t pos) | ||
791 | { | ||
792 | if (!pos) | ||
793 | return SEQ_START_TOKEN; | ||
794 | |||
795 | return seq_hlist_start_rcu(head, pos - 1); | ||
796 | } | ||
797 | EXPORT_SYMBOL(seq_hlist_start_head_rcu); | ||
798 | |||
799 | /** | ||
800 | * seq_hlist_next_rcu - move to the next position of the hlist protected by RCU | ||
801 | * @v: the current iterator | ||
802 | * @head: the head of the hlist | ||
803 | * @pos: the current posision | ||
804 | * | ||
805 | * Called at seq_file->op->next(). | ||
806 | * | ||
807 | * This list-traversal primitive may safely run concurrently with | ||
808 | * the _rcu list-mutation primitives such as hlist_add_head_rcu() | ||
809 | * as long as the traversal is guarded by rcu_read_lock(). | ||
810 | */ | ||
811 | struct hlist_node *seq_hlist_next_rcu(void *v, | ||
812 | struct hlist_head *head, | ||
813 | loff_t *ppos) | ||
814 | { | ||
815 | struct hlist_node *node = v; | ||
816 | |||
817 | ++*ppos; | ||
818 | if (v == SEQ_START_TOKEN) | ||
819 | return rcu_dereference(head->first); | ||
820 | else | ||
821 | return rcu_dereference(node->next); | ||
822 | } | ||
823 | EXPORT_SYMBOL(seq_hlist_next_rcu); | ||
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 70504fcf14cd..14dafd608230 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -245,7 +245,7 @@ typedef struct xfs_mount { | |||
245 | struct xfs_qmops *m_qm_ops; /* vector of XQM ops */ | 245 | struct xfs_qmops *m_qm_ops; /* vector of XQM ops */ |
246 | atomic_t m_active_trans; /* number trans frozen */ | 246 | atomic_t m_active_trans; /* number trans frozen */ |
247 | #ifdef HAVE_PERCPU_SB | 247 | #ifdef HAVE_PERCPU_SB |
248 | xfs_icsb_cnts_t *m_sb_cnts; /* per-cpu superblock counters */ | 248 | xfs_icsb_cnts_t __percpu *m_sb_cnts; /* per-cpu superblock counters */ |
249 | unsigned long m_icsb_counters; /* disabled per-cpu counters */ | 249 | unsigned long m_icsb_counters; /* disabled per-cpu counters */ |
250 | struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */ | 250 | struct notifier_block m_icsb_notifier; /* hotplug cpu notifier */ |
251 | struct mutex m_icsb_mutex; /* balancer sync lock */ | 251 | struct mutex m_icsb_mutex; /* balancer sync lock */ |