diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/bio.c | 9 | ||||
| -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/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/partitions/check.c | 7 | ||||
| -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, 398 insertions, 412 deletions
| @@ -507,10 +507,8 @@ int bio_get_nr_vecs(struct block_device *bdev) | |||
| 507 | int nr_pages; | 507 | int nr_pages; |
| 508 | 508 | ||
| 509 | nr_pages = ((queue_max_sectors(q) << 9) + PAGE_SIZE - 1) >> PAGE_SHIFT; | 509 | nr_pages = ((queue_max_sectors(q) << 9) + PAGE_SIZE - 1) >> PAGE_SHIFT; |
| 510 | if (nr_pages > queue_max_phys_segments(q)) | 510 | if (nr_pages > queue_max_segments(q)) |
| 511 | nr_pages = queue_max_phys_segments(q); | 511 | nr_pages = queue_max_segments(q); |
| 512 | if (nr_pages > queue_max_hw_segments(q)) | ||
| 513 | nr_pages = queue_max_hw_segments(q); | ||
| 514 | 512 | ||
| 515 | return nr_pages; | 513 | return nr_pages; |
| 516 | } | 514 | } |
| @@ -575,8 +573,7 @@ static int __bio_add_page(struct request_queue *q, struct bio *bio, struct page | |||
| 575 | * make this too complex. | 573 | * make this too complex. |
| 576 | */ | 574 | */ |
| 577 | 575 | ||
| 578 | while (bio->bi_phys_segments >= queue_max_phys_segments(q) | 576 | while (bio->bi_phys_segments >= queue_max_segments(q)) { |
| 579 | || bio->bi_phys_segments >= queue_max_hw_segments(q)) { | ||
| 580 | 577 | ||
| 581 | if (retried_segments) | 578 | if (retried_segments) |
| 582 | return 0; | 579 | return 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/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/partitions/check.c b/fs/partitions/check.c index 64bc8998ac9a..e8865c11777f 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
| @@ -412,9 +412,10 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
| 412 | pdev = part_to_dev(p); | 412 | pdev = part_to_dev(p); |
| 413 | 413 | ||
| 414 | p->start_sect = start; | 414 | p->start_sect = start; |
| 415 | p->alignment_offset = queue_sector_alignment_offset(disk->queue, start); | 415 | p->alignment_offset = |
| 416 | p->discard_alignment = queue_sector_discard_alignment(disk->queue, | 416 | queue_limit_alignment_offset(&disk->queue->limits, start); |
| 417 | start); | 417 | p->discard_alignment = |
| 418 | queue_limit_discard_alignment(&disk->queue->limits, start); | ||
| 418 | p->nr_sects = len; | 419 | p->nr_sects = len; |
| 419 | p->partno = partno; | 420 | p->partno = partno; |
| 420 | p->policy = get_disk_ro(disk); | 421 | p->policy = get_disk_ro(disk); |
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 */ |
