diff options
Diffstat (limited to 'fs')
36 files changed, 336 insertions, 176 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index be7288184fa9..0ea965c3bb7d 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
| @@ -427,6 +427,8 @@ v9fs_create(struct inode *dir, | |||
| 427 | 427 | ||
| 428 | v9fs_mistat2inode(fcall->params.rstat.stat, file_inode, sb); | 428 | v9fs_mistat2inode(fcall->params.rstat.stat, file_inode, sb); |
| 429 | kfree(fcall); | 429 | kfree(fcall); |
| 430 | fcall = NULL; | ||
| 431 | file_dentry->d_op = &v9fs_dentry_operations; | ||
| 430 | d_instantiate(file_dentry, file_inode); | 432 | d_instantiate(file_dentry, file_inode); |
| 431 | 433 | ||
| 432 | if (perm & V9FS_DMDIR) { | 434 | if (perm & V9FS_DMDIR) { |
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index 6bded10c0d50..943ef9b82244 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
| @@ -1,10 +1,12 @@ | |||
| 1 | Version 1.39 | 1 | Version 1.39 |
| 2 | ------------ | 2 | ------------ |
| 3 | Defer close of a file handle slightly if pending writes depend on that file handle | 3 | Defer close of a file handle slightly if pending writes depend on that handle |
| 4 | (this reduces the EBADF bad file handle errors that can be logged under heavy | 4 | (this reduces the EBADF bad file handle errors that can be logged under heavy |
| 5 | stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 | 5 | stress on writes). Modify cifs Kconfig options to expose CONFIG_CIFS_STATS2 |
| 6 | Fix SFU style symlinks and mknod needed for servers which do not support the CIFS | 6 | Fix SFU style symlinks and mknod needed for servers which do not support the |
| 7 | Unix Extensions. Fix setfacl/getfacl on bigendian. | 7 | CIFS Unix Extensions. Fix setfacl/getfacl on bigendian. Timeout negative |
| 8 | dentries so files that the client sees as deleted but that later get created | ||
| 9 | on the server will be recognized. Add client side permission check on setattr. | ||
| 8 | 10 | ||
| 9 | Version 1.38 | 11 | Version 1.38 |
| 10 | ------------ | 12 | ------------ |
diff --git a/fs/cifs/README b/fs/cifs/README index bb90941826ad..e5d09a2fc7a5 100644 --- a/fs/cifs/README +++ b/fs/cifs/README | |||
| @@ -278,7 +278,9 @@ A partial list of the supported mount options follows: | |||
| 278 | (such as Windows), permissions can also be checked at the | 278 | (such as Windows), permissions can also be checked at the |
| 279 | client, and a crude form of client side permission checking | 279 | client, and a crude form of client side permission checking |
| 280 | can be enabled by specifying file_mode and dir_mode on | 280 | can be enabled by specifying file_mode and dir_mode on |
| 281 | the client | 281 | the client. Note that the mount.cifs helper must be |
| 282 | at version 1.10 or higher to support specifying the uid | ||
| 283 | (or gid) in non-numberic form. | ||
| 282 | gid If CIFS Unix extensions are not supported by the server | 284 | gid If CIFS Unix extensions are not supported by the server |
| 283 | this overrides the default gid for inodes. | 285 | this overrides the default gid for inodes. |
| 284 | file_mode If CIFS Unix extensions are not supported by the server | 286 | file_mode If CIFS Unix extensions are not supported by the server |
| @@ -345,7 +347,10 @@ A partial list of the supported mount options follows: | |||
| 345 | client system. It is typically only needed when the server | 347 | client system. It is typically only needed when the server |
| 346 | supports the CIFS Unix Extensions but the UIDs/GIDs on the | 348 | supports the CIFS Unix Extensions but the UIDs/GIDs on the |
| 347 | client and server system do not match closely enough to allow | 349 | client and server system do not match closely enough to allow |
| 348 | access by the user doing the mount. | 350 | access by the user doing the mount, but it may be useful with |
| 351 | non CIFS Unix Extension mounts for cases in which the default | ||
| 352 | mode is specified on the mount but is not to be enforced on the | ||
| 353 | client (e.g. perhaps when MultiUserMount is enabled) | ||
| 349 | Note that this does not affect the normal ACL check on the | 354 | Note that this does not affect the normal ACL check on the |
| 350 | target machine done by the server software (of the server | 355 | target machine done by the server software (of the server |
| 351 | ACL against the user name provided at mount time). | 356 | ACL against the user name provided at mount time). |
| @@ -368,15 +373,21 @@ A partial list of the supported mount options follows: | |||
| 368 | setuids If the CIFS Unix extensions are negotiated with the server | 373 | setuids If the CIFS Unix extensions are negotiated with the server |
| 369 | the client will attempt to set the effective uid and gid of | 374 | the client will attempt to set the effective uid and gid of |
| 370 | the local process on newly created files, directories, and | 375 | the local process on newly created files, directories, and |
| 371 | devices (create, mkdir, mknod). | 376 | devices (create, mkdir, mknod). If the CIFS Unix Extensions |
| 377 | are not negotiated, for newly created files and directories | ||
| 378 | instead of using the default uid and gid specified on the | ||
| 379 | the mount, cache the new file's uid and gid locally which means | ||
| 380 | that the uid for the file can change when the inode is | ||
| 381 | reloaded (or the user remounts the share). | ||
| 372 | nosetuids The client will not attempt to set the uid and gid on | 382 | nosetuids The client will not attempt to set the uid and gid on |
| 373 | on newly created files, directories, and devices (create, | 383 | on newly created files, directories, and devices (create, |
| 374 | mkdir, mknod) which will result in the server setting the | 384 | mkdir, mknod) which will result in the server setting the |
| 375 | uid and gid to the default (usually the server uid of the | 385 | uid and gid to the default (usually the server uid of the |
| 376 | user who mounted the share). Letting the server (rather than | 386 | user who mounted the share). Letting the server (rather than |
| 377 | the client) set the uid and gid is the default. This | 387 | the client) set the uid and gid is the default. If the CIFS |
| 378 | parameter has no effect if the CIFS Unix Extensions are not | 388 | Unix Extensions are not negotiated then the uid and gid for |
| 379 | negotiated. | 389 | new files will appear to be the uid (gid) of the mounter or the |
| 390 | uid (gid) parameter specified on the mount. | ||
| 380 | netbiosname When mounting to servers via port 139, specifies the RFC1001 | 391 | netbiosname When mounting to servers via port 139, specifies the RFC1001 |
| 381 | source name to use to represent the client netbios machine | 392 | source name to use to represent the client netbios machine |
| 382 | name when doing the RFC1001 netbios session initialize. | 393 | name when doing the RFC1001 netbios session initialize. |
| @@ -418,6 +429,13 @@ A partial list of the supported mount options follows: | |||
| 418 | byte range locks). | 429 | byte range locks). |
| 419 | remount remount the share (often used to change from ro to rw mounts | 430 | remount remount the share (often used to change from ro to rw mounts |
| 420 | or vice versa) | 431 | or vice versa) |
| 432 | sfu When the CIFS Unix Extensions are not negotiated, attempt to | ||
| 433 | create device files and fifos in a format compatible with | ||
| 434 | Services for Unix (SFU). In addition retrieve bits 10-12 | ||
| 435 | of the mode via the SETFILEBITS extended attribute (as | ||
| 436 | SFU does). In the future the bottom 9 bits of the mode | ||
| 437 | mode also will be emulated using queries of the security | ||
| 438 | descriptor (ACL). | ||
| 421 | 439 | ||
| 422 | The mount.cifs mount helper also accepts a few mount options before -o | 440 | The mount.cifs mount helper also accepts a few mount options before -o |
| 423 | including: | 441 | including: |
diff --git a/fs/cifs/TODO b/fs/cifs/TODO index c909298d11ed..fc34c74ec4be 100644 --- a/fs/cifs/TODO +++ b/fs/cifs/TODO | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | version 1.37 October 9, 2005 | 1 | Version 1.39 November 30, 2005 |
| 2 | 2 | ||
| 3 | A Partial List of Missing Features | 3 | A Partial List of Missing Features |
| 4 | ================================== | 4 | ================================== |
| @@ -58,7 +58,7 @@ o) Improve performance of readpages by sending more than one read | |||
| 58 | at a time when 8 pages or more are requested. In conjuntion | 58 | at a time when 8 pages or more are requested. In conjuntion |
| 59 | add support for async_cifs_readpages. | 59 | add support for async_cifs_readpages. |
| 60 | 60 | ||
| 61 | p) Add support for storing symlink and fifo info to Windows servers | 61 | p) Add support for storing symlink info to Windows servers |
| 62 | in the Extended Attribute format their SFU clients would recognize. | 62 | in the Extended Attribute format their SFU clients would recognize. |
| 63 | 63 | ||
| 64 | q) Finish fcntl D_NOTIFY support so kde and gnome file list windows | 64 | q) Finish fcntl D_NOTIFY support so kde and gnome file list windows |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 51548ed2e9cc..2a13a2bac8f1 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
| 33 | #include <linux/vfs.h> | 33 | #include <linux/vfs.h> |
| 34 | #include <linux/mempool.h> | 34 | #include <linux/mempool.h> |
| 35 | #include <linux/delay.h> | ||
| 35 | #include "cifsfs.h" | 36 | #include "cifsfs.h" |
| 36 | #include "cifspdu.h" | 37 | #include "cifspdu.h" |
| 37 | #define DECLARE_GLOBALS_HERE | 38 | #define DECLARE_GLOBALS_HERE |
| @@ -429,6 +430,11 @@ static void cifs_umount_begin(struct super_block * sblock) | |||
| 429 | { | 430 | { |
| 430 | cFYI(1,("wake up tasks now - umount begin not complete")); | 431 | cFYI(1,("wake up tasks now - umount begin not complete")); |
| 431 | wake_up_all(&tcon->ses->server->request_q); | 432 | wake_up_all(&tcon->ses->server->request_q); |
| 433 | wake_up_all(&tcon->ses->server->response_q); | ||
| 434 | msleep(1); /* yield */ | ||
| 435 | /* we have to kick the requests once more */ | ||
| 436 | wake_up_all(&tcon->ses->server->response_q); | ||
| 437 | msleep(1); | ||
| 432 | } | 438 | } |
| 433 | /* BB FIXME - finish add checks for tidStatus BB */ | 439 | /* BB FIXME - finish add checks for tidStatus BB */ |
| 434 | 440 | ||
| @@ -895,6 +901,9 @@ static int cifs_oplock_thread(void * dummyarg) | |||
| 895 | 901 | ||
| 896 | static int cifs_dnotify_thread(void * dummyarg) | 902 | static int cifs_dnotify_thread(void * dummyarg) |
| 897 | { | 903 | { |
| 904 | struct list_head *tmp; | ||
| 905 | struct cifsSesInfo *ses; | ||
| 906 | |||
| 898 | daemonize("cifsdnotifyd"); | 907 | daemonize("cifsdnotifyd"); |
| 899 | allow_signal(SIGTERM); | 908 | allow_signal(SIGTERM); |
| 900 | 909 | ||
| @@ -903,7 +912,19 @@ static int cifs_dnotify_thread(void * dummyarg) | |||
| 903 | if(try_to_freeze()) | 912 | if(try_to_freeze()) |
| 904 | continue; | 913 | continue; |
| 905 | set_current_state(TASK_INTERRUPTIBLE); | 914 | set_current_state(TASK_INTERRUPTIBLE); |
| 906 | schedule_timeout(39*HZ); | 915 | schedule_timeout(15*HZ); |
| 916 | read_lock(&GlobalSMBSeslock); | ||
| 917 | /* check if any stuck requests that need | ||
| 918 | to be woken up and wakeq so the | ||
| 919 | thread can wake up and error out */ | ||
| 920 | list_for_each(tmp, &GlobalSMBSessionList) { | ||
| 921 | ses = list_entry(tmp, struct cifsSesInfo, | ||
| 922 | cifsSessionList); | ||
| 923 | if(ses && ses->server && | ||
| 924 | atomic_read(&ses->server->inFlight)) | ||
| 925 | wake_up_all(&ses->server->response_q); | ||
| 926 | } | ||
| 927 | read_unlock(&GlobalSMBSeslock); | ||
| 907 | } while(!signal_pending(current)); | 928 | } while(!signal_pending(current)); |
| 908 | complete_and_exit (&cifs_dnotify_exited, 0); | 929 | complete_and_exit (&cifs_dnotify_exited, 0); |
| 909 | } | 930 | } |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index d179b0c3eee4..6867e556d37e 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -90,6 +90,18 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
| 90 | check for tcp and smb session status done differently | 90 | check for tcp and smb session status done differently |
| 91 | for those three - in the calling routine */ | 91 | for those three - in the calling routine */ |
| 92 | if(tcon) { | 92 | if(tcon) { |
| 93 | if(tcon->tidStatus == CifsExiting) { | ||
| 94 | /* only tree disconnect, open, and write, | ||
| 95 | (and ulogoff which does not have tcon) | ||
| 96 | are allowed as we start force umount */ | ||
| 97 | if((smb_command != SMB_COM_WRITE_ANDX) && | ||
| 98 | (smb_command != SMB_COM_OPEN_ANDX) && | ||
| 99 | (smb_command != SMB_COM_TREE_DISCONNECT)) { | ||
| 100 | cFYI(1,("can not send cmd %d while umounting", | ||
| 101 | smb_command)); | ||
| 102 | return -ENODEV; | ||
| 103 | } | ||
| 104 | } | ||
| 93 | if((tcon->ses) && (tcon->ses->status != CifsExiting) && | 105 | if((tcon->ses) && (tcon->ses->status != CifsExiting) && |
| 94 | (tcon->ses->server)){ | 106 | (tcon->ses->server)){ |
| 95 | struct nls_table *nls_codepage; | 107 | struct nls_table *nls_codepage; |
| @@ -187,6 +199,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon, | |||
| 187 | check for tcp and smb session status done differently | 199 | check for tcp and smb session status done differently |
| 188 | for those three - in the calling routine */ | 200 | for those three - in the calling routine */ |
| 189 | if(tcon) { | 201 | if(tcon) { |
| 202 | if(tcon->tidStatus == CifsExiting) { | ||
| 203 | /* only tree disconnect, open, and write, | ||
| 204 | (and ulogoff which does not have tcon) | ||
| 205 | are allowed as we start force umount */ | ||
| 206 | if((smb_command != SMB_COM_WRITE_ANDX) && | ||
| 207 | (smb_command != SMB_COM_OPEN_ANDX) && | ||
| 208 | (smb_command != SMB_COM_TREE_DISCONNECT)) { | ||
| 209 | cFYI(1,("can not send cmd %d while umounting", | ||
| 210 | smb_command)); | ||
| 211 | return -ENODEV; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 190 | if((tcon->ses) && (tcon->ses->status != CifsExiting) && | 215 | if((tcon->ses) && (tcon->ses->status != CifsExiting) && |
| 191 | (tcon->ses->server)){ | 216 | (tcon->ses->server)){ |
| 192 | struct nls_table *nls_codepage; | 217 | struct nls_table *nls_codepage; |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 16b21522e8fe..32cc96cafa3e 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -228,8 +228,15 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 228 | else { | 228 | else { |
| 229 | rc = cifs_get_inode_info(&newinode, full_path, | 229 | rc = cifs_get_inode_info(&newinode, full_path, |
| 230 | buf, inode->i_sb,xid); | 230 | buf, inode->i_sb,xid); |
| 231 | if(newinode) | 231 | if(newinode) { |
| 232 | newinode->i_mode = mode; | 232 | newinode->i_mode = mode; |
| 233 | if((oplock & CIFS_CREATE_ACTION) && | ||
| 234 | (cifs_sb->mnt_cifs_flags & | ||
| 235 | CIFS_MOUNT_SET_UID)) { | ||
| 236 | newinode->i_uid = current->fsuid; | ||
| 237 | newinode->i_gid = current->fsgid; | ||
| 238 | } | ||
| 239 | } | ||
| 233 | } | 240 | } |
| 234 | 241 | ||
| 235 | if (rc != 0) { | 242 | if (rc != 0) { |
| @@ -465,12 +472,20 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name | |||
| 465 | direntry->d_op = &cifs_dentry_ops; | 472 | direntry->d_op = &cifs_dentry_ops; |
| 466 | d_add(direntry, newInode); | 473 | d_add(direntry, newInode); |
| 467 | 474 | ||
| 468 | /* since paths are not looked up by component - the parent directories are presumed to be good here */ | 475 | /* since paths are not looked up by component - the parent |
| 476 | directories are presumed to be good here */ | ||
| 469 | renew_parental_timestamps(direntry); | 477 | renew_parental_timestamps(direntry); |
| 470 | 478 | ||
| 471 | } else if (rc == -ENOENT) { | 479 | } else if (rc == -ENOENT) { |
| 472 | rc = 0; | 480 | rc = 0; |
| 481 | direntry->d_time = jiffies; | ||
| 482 | if (pTcon->nocase) | ||
| 483 | direntry->d_op = &cifs_ci_dentry_ops; | ||
| 484 | else | ||
| 485 | direntry->d_op = &cifs_dentry_ops; | ||
| 473 | d_add(direntry, NULL); | 486 | d_add(direntry, NULL); |
| 487 | /* if it was once a directory (but how can we tell?) we could do | ||
| 488 | shrink_dcache_parent(direntry); */ | ||
| 474 | } else { | 489 | } else { |
| 475 | cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", | 490 | cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", |
| 476 | rc,full_path)); | 491 | rc,full_path)); |
| @@ -489,21 +504,20 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) | |||
| 489 | { | 504 | { |
| 490 | int isValid = 1; | 505 | int isValid = 1; |
| 491 | 506 | ||
| 492 | /* lock_kernel(); *//* surely we do not want to lock the kernel for a whole network round trip which could take seconds */ | ||
| 493 | |||
| 494 | if (direntry->d_inode) { | 507 | if (direntry->d_inode) { |
| 495 | if (cifs_revalidate(direntry)) { | 508 | if (cifs_revalidate(direntry)) { |
| 496 | /* unlock_kernel(); */ | ||
| 497 | return 0; | 509 | return 0; |
| 498 | } | 510 | } |
| 499 | } else { | 511 | } else { |
| 500 | cFYI(1, | 512 | cFYI(1, ("neg dentry 0x%p name = %s", |
| 501 | ("In cifs_d_revalidate with no inode but name = %s and dentry 0x%p", | 513 | direntry, direntry->d_name.name)); |
| 502 | direntry->d_name.name, direntry)); | 514 | if(time_after(jiffies, direntry->d_time + HZ) || |
| 515 | !lookupCacheEnabled) { | ||
| 516 | d_drop(direntry); | ||
| 517 | isValid = 0; | ||
| 518 | } | ||
| 503 | } | 519 | } |
| 504 | 520 | ||
| 505 | /* unlock_kernel(); */ | ||
| 506 | |||
| 507 | return isValid; | 521 | return isValid; |
| 508 | } | 522 | } |
| 509 | 523 | ||
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 05b525812adb..411c1f7f84da 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -710,7 +710,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 710 | char *full_path = NULL; | 710 | char *full_path = NULL; |
| 711 | struct inode *newinode = NULL; | 711 | struct inode *newinode = NULL; |
| 712 | 712 | ||
| 713 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode)); | 713 | cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode)); |
| 714 | 714 | ||
| 715 | xid = GetXid(); | 715 | xid = GetXid(); |
| 716 | 716 | ||
| @@ -768,6 +768,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 768 | /* BB to be implemented via Windows secrty descriptors | 768 | /* BB to be implemented via Windows secrty descriptors |
| 769 | eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, | 769 | eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, |
| 770 | -1, -1, local_nls); */ | 770 | -1, -1, local_nls); */ |
| 771 | if(direntry->d_inode) { | ||
| 772 | direntry->d_inode->i_mode = mode; | ||
| 773 | direntry->d_inode->i_mode |= S_IFDIR; | ||
| 774 | if(cifs_sb->mnt_cifs_flags & | ||
| 775 | CIFS_MOUNT_SET_UID) { | ||
| 776 | direntry->d_inode->i_uid = | ||
| 777 | current->fsuid; | ||
| 778 | direntry->d_inode->i_gid = | ||
| 779 | current->fsgid; | ||
| 780 | } | ||
| 781 | } | ||
| 771 | } | 782 | } |
| 772 | } | 783 | } |
| 773 | kfree(full_path); | 784 | kfree(full_path); |
| @@ -1039,14 +1050,20 @@ int cifs_revalidate(struct dentry *direntry) | |||
| 1039 | filemap_fdatawrite(direntry->d_inode->i_mapping); | 1050 | filemap_fdatawrite(direntry->d_inode->i_mapping); |
| 1040 | } | 1051 | } |
| 1041 | if (invalidate_inode) { | 1052 | if (invalidate_inode) { |
| 1042 | if (direntry->d_inode->i_mapping) | 1053 | /* shrink_dcache not necessary now that cifs dentry ops |
| 1043 | filemap_fdatawait(direntry->d_inode->i_mapping); | 1054 | are exported for negative dentries */ |
| 1044 | /* may eventually have to do this for open files too */ | 1055 | /* if(S_ISDIR(direntry->d_inode->i_mode)) |
| 1045 | if (list_empty(&(cifsInode->openFileList))) { | 1056 | shrink_dcache_parent(direntry); */ |
| 1046 | /* Has changed on server - flush read ahead pages */ | 1057 | if (S_ISREG(direntry->d_inode->i_mode)) { |
| 1047 | cFYI(1, ("Invalidating read ahead data on " | 1058 | if (direntry->d_inode->i_mapping) |
| 1048 | "closed file")); | 1059 | filemap_fdatawait(direntry->d_inode->i_mapping); |
| 1049 | invalidate_remote_inode(direntry->d_inode); | 1060 | /* may eventually have to do this for open files too */ |
| 1061 | if (list_empty(&(cifsInode->openFileList))) { | ||
| 1062 | /* changed on server - flush read ahead pages */ | ||
| 1063 | cFYI(1, ("Invalidating read ahead data on " | ||
| 1064 | "closed file")); | ||
| 1065 | invalidate_remote_inode(direntry->d_inode); | ||
| 1066 | } | ||
| 1050 | } | 1067 | } |
| 1051 | } | 1068 | } |
| 1052 | /* up(&direntry->d_inode->i_sem); */ | 1069 | /* up(&direntry->d_inode->i_sem); */ |
| @@ -1105,9 +1122,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 1105 | 1122 | ||
| 1106 | cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ", | 1123 | cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ", |
| 1107 | direntry->d_name.name, attrs->ia_valid)); | 1124 | direntry->d_name.name, attrs->ia_valid)); |
| 1125 | |||
| 1108 | cifs_sb = CIFS_SB(direntry->d_inode->i_sb); | 1126 | cifs_sb = CIFS_SB(direntry->d_inode->i_sb); |
| 1109 | pTcon = cifs_sb->tcon; | 1127 | pTcon = cifs_sb->tcon; |
| 1110 | 1128 | ||
| 1129 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) { | ||
| 1130 | /* check if we have permission to change attrs */ | ||
| 1131 | rc = inode_change_ok(direntry->d_inode, attrs); | ||
| 1132 | if(rc < 0) { | ||
| 1133 | FreeXid(xid); | ||
| 1134 | return rc; | ||
| 1135 | } else | ||
| 1136 | rc = 0; | ||
| 1137 | } | ||
| 1138 | |||
| 1111 | down(&direntry->d_sb->s_vfs_rename_sem); | 1139 | down(&direntry->d_sb->s_vfs_rename_sem); |
| 1112 | full_path = build_path_from_dentry(direntry); | 1140 | full_path = build_path_from_dentry(direntry); |
| 1113 | up(&direntry->d_sb->s_vfs_rename_sem); | 1141 | up(&direntry->d_sb->s_vfs_rename_sem); |
| @@ -1147,7 +1175,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs) | |||
| 1147 | 1 /* 45 seconds */); | 1175 | 1 /* 45 seconds */); |
| 1148 | cFYI(1,("Wrt seteof rc %d", rc)); | 1176 | cFYI(1,("Wrt seteof rc %d", rc)); |
| 1149 | } | 1177 | } |
| 1150 | } | 1178 | } else |
| 1179 | rc = -EINVAL; | ||
| 1180 | |||
| 1151 | if (rc != 0) { | 1181 | if (rc != 0) { |
| 1152 | /* Set file size by pathname rather than by handle | 1182 | /* Set file size by pathname rather than by handle |
| 1153 | either because no valid, writeable file handle for | 1183 | either because no valid, writeable file handle for |
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index ca27a82c54cd..94baf6c8ecbd 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c | |||
| @@ -397,12 +397,12 @@ checkSMBhdr(struct smb_hdr *smb, __u16 mid) | |||
| 397 | if(smb->Command == SMB_COM_LOCKING_ANDX) | 397 | if(smb->Command == SMB_COM_LOCKING_ANDX) |
| 398 | return 0; | 398 | return 0; |
| 399 | else | 399 | else |
| 400 | cERROR(1, ("Rcvd Request not response ")); | 400 | cERROR(1, ("Rcvd Request not response")); |
| 401 | } | 401 | } |
| 402 | } else { /* bad signature or mid */ | 402 | } else { /* bad signature or mid */ |
| 403 | if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) | 403 | if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) |
| 404 | cERROR(1, | 404 | cERROR(1, |
| 405 | ("Bad protocol string signature header %x ", | 405 | ("Bad protocol string signature header %x", |
| 406 | *(unsigned int *) smb->Protocol)); | 406 | *(unsigned int *) smb->Protocol)); |
| 407 | if (mid != smb->Mid) | 407 | if (mid != smb->Mid) |
| 408 | cERROR(1, ("Mids do not match")); | 408 | cERROR(1, ("Mids do not match")); |
| @@ -417,7 +417,7 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
| 417 | __u32 len = smb->smb_buf_length; | 417 | __u32 len = smb->smb_buf_length; |
| 418 | __u32 clc_len; /* calculated length */ | 418 | __u32 clc_len; /* calculated length */ |
| 419 | cFYI(0, | 419 | cFYI(0, |
| 420 | ("Entering checkSMB with Length: %x, smb_buf_length: %x ", | 420 | ("Entering checkSMB with Length: %x, smb_buf_length: %x", |
| 421 | length, len)); | 421 | length, len)); |
| 422 | if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || | 422 | if (((unsigned int)length < 2 + sizeof (struct smb_hdr)) || |
| 423 | (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { | 423 | (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4)) { |
| @@ -451,9 +451,16 @@ checkSMB(struct smb_hdr *smb, __u16 mid, int length) | |||
| 451 | cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); | 451 | cERROR(1, ("bad smb size detected for Mid=%d", smb->Mid)); |
| 452 | /* Windows XP can return a few bytes too much, presumably | 452 | /* Windows XP can return a few bytes too much, presumably |
| 453 | an illegal pad, at the end of byte range lock responses | 453 | an illegal pad, at the end of byte range lock responses |
| 454 | so we allow for up to eight byte pad, as long as actual | 454 | so we allow for that three byte pad, as long as actual |
| 455 | received length is as long or longer than calculated length */ | 455 | received length is as long or longer than calculated length */ |
| 456 | if((4+len > clc_len) && (len <= clc_len + 3)) | 456 | /* We have now had to extend this more, since there is a |
| 457 | case in which it needs to be bigger still to handle a | ||
| 458 | malformed response to transact2 findfirst from WinXP when | ||
| 459 | access denied is returned and thus bcc and wct are zero | ||
| 460 | but server says length is 0x21 bytes too long as if the server | ||
| 461 | forget to reset the smb rfc1001 length when it reset the | ||
| 462 | wct and bcc to minimum size and drop the t2 parms and data */ | ||
| 463 | if((4+len > clc_len) && (len <= clc_len + 512)) | ||
| 457 | return 0; | 464 | return 0; |
| 458 | else | 465 | else |
| 459 | return 1; | 466 | return 1; |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index f7814689844b..5de74d216fdd 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
| @@ -330,7 +330,7 @@ static const struct { | |||
| 330 | ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { | 330 | ERRHRD, ERRgeneral, NT_STATUS_ACCOUNT_RESTRICTION}, { |
| 331 | ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { | 331 | ERRSRV, 2241, NT_STATUS_INVALID_LOGON_HOURS}, { |
| 332 | ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { | 332 | ERRSRV, 2240, NT_STATUS_INVALID_WORKSTATION}, { |
| 333 | ERRSRV, 2242, NT_STATUS_PASSWORD_EXPIRED}, { | 333 | ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_EXPIRED}, { |
| 334 | ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { | 334 | ERRSRV, 2239, NT_STATUS_ACCOUNT_DISABLED}, { |
| 335 | ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { | 335 | ERRHRD, ERRgeneral, NT_STATUS_NONE_MAPPED}, { |
| 336 | ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { | 336 | ERRHRD, ERRgeneral, NT_STATUS_TOO_MANY_LUIDS_REQUESTED}, { |
| @@ -676,7 +676,7 @@ static const struct { | |||
| 676 | ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, { | 676 | ERRDOS, 193, NT_STATUS_IMAGE_CHECKSUM_MISMATCH}, { |
| 677 | ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, { | 677 | ERRHRD, ERRgeneral, NT_STATUS_LOST_WRITEBEHIND_DATA}, { |
| 678 | ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, { | 678 | ERRHRD, ERRgeneral, NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID}, { |
| 679 | ERRSRV, 2242, NT_STATUS_PASSWORD_MUST_CHANGE}, { | 679 | ERRSRV, ERRpasswordExpired, NT_STATUS_PASSWORD_MUST_CHANGE}, { |
| 680 | ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, { | 680 | ERRHRD, ERRgeneral, NT_STATUS_NOT_FOUND}, { |
| 681 | ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, { | 681 | ERRHRD, ERRgeneral, NT_STATUS_NOT_TINY_STREAM}, { |
| 682 | ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, { | 682 | ERRHRD, ERRgeneral, NT_STATUS_RECOVERY_FAILURE}, { |
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 41a9659c16bc..f8871196098c 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c | |||
| @@ -515,6 +515,7 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses, | |||
| 515 | *pbytes_returned = in_buf->smb_buf_length; | 515 | *pbytes_returned = in_buf->smb_buf_length; |
| 516 | 516 | ||
| 517 | /* BB special case reconnect tid and uid here? */ | 517 | /* BB special case reconnect tid and uid here? */ |
| 518 | /* BB special case Errbadpassword and pwdexpired here */ | ||
| 518 | rc = map_smb_to_linux_error(in_buf); | 519 | rc = map_smb_to_linux_error(in_buf); |
| 519 | 520 | ||
| 520 | /* convert ByteCount if necessary */ | 521 | /* convert ByteCount if necessary */ |
diff --git a/fs/dquot.c b/fs/dquot.c index 05b60283c9c2..2a62b3dc20ec 100644 --- a/fs/dquot.c +++ b/fs/dquot.c | |||
| @@ -1513,10 +1513,16 @@ int vfs_quota_on_mount(struct super_block *sb, char *qf_name, | |||
| 1513 | if (IS_ERR(dentry)) | 1513 | if (IS_ERR(dentry)) |
| 1514 | return PTR_ERR(dentry); | 1514 | return PTR_ERR(dentry); |
| 1515 | 1515 | ||
| 1516 | if (!dentry->d_inode) { | ||
| 1517 | error = -ENOENT; | ||
| 1518 | goto out; | ||
| 1519 | } | ||
| 1520 | |||
| 1516 | error = security_quota_on(dentry); | 1521 | error = security_quota_on(dentry); |
| 1517 | if (!error) | 1522 | if (!error) |
| 1518 | error = vfs_quota_on_inode(dentry->d_inode, type, format_id); | 1523 | error = vfs_quota_on_inode(dentry->d_inode, type, format_id); |
| 1519 | 1524 | ||
| 1525 | out: | ||
| 1520 | dput(dentry); | 1526 | dput(dentry); |
| 1521 | return error; | 1527 | return error; |
| 1522 | } | 1528 | } |
| @@ -306,9 +306,6 @@ void install_arg_page(struct vm_area_struct *vma, | |||
| 306 | struct page *page, unsigned long address) | 306 | struct page *page, unsigned long address) |
| 307 | { | 307 | { |
| 308 | struct mm_struct *mm = vma->vm_mm; | 308 | struct mm_struct *mm = vma->vm_mm; |
| 309 | pgd_t * pgd; | ||
| 310 | pud_t * pud; | ||
| 311 | pmd_t * pmd; | ||
| 312 | pte_t * pte; | 309 | pte_t * pte; |
| 313 | spinlock_t *ptl; | 310 | spinlock_t *ptl; |
| 314 | 311 | ||
| @@ -316,14 +313,7 @@ void install_arg_page(struct vm_area_struct *vma, | |||
| 316 | goto out; | 313 | goto out; |
| 317 | 314 | ||
| 318 | flush_dcache_page(page); | 315 | flush_dcache_page(page); |
| 319 | pgd = pgd_offset(mm, address); | 316 | pte = get_locked_pte(mm, address, &ptl); |
| 320 | pud = pud_alloc(mm, pgd, address); | ||
| 321 | if (!pud) | ||
| 322 | goto out; | ||
| 323 | pmd = pmd_alloc(mm, pud, address); | ||
| 324 | if (!pmd) | ||
| 325 | goto out; | ||
| 326 | pte = pte_alloc_map_lock(mm, pmd, address, &ptl); | ||
| 327 | if (!pte) | 317 | if (!pte) |
| 328 | goto out; | 318 | goto out; |
| 329 | if (!pte_none(*pte)) { | 319 | if (!pte_none(*pte)) { |
diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 1be78b4b4de9..6104ad310507 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c | |||
| @@ -767,6 +767,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) | |||
| 767 | if (input->group != EXT3_SB(sb)->s_groups_count) { | 767 | if (input->group != EXT3_SB(sb)->s_groups_count) { |
| 768 | ext3_warning(sb, __FUNCTION__, | 768 | ext3_warning(sb, __FUNCTION__, |
| 769 | "multiple resizers run on filesystem!\n"); | 769 | "multiple resizers run on filesystem!\n"); |
| 770 | err = -EBUSY; | ||
| 770 | goto exit_journal; | 771 | goto exit_journal; |
| 771 | } | 772 | } |
| 772 | 773 | ||
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index c045cc70c749..51f5da652771 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -74,6 +74,24 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd) | |||
| 74 | return 1; | 74 | return 1; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | static int dir_alias(struct inode *inode) | ||
| 78 | { | ||
| 79 | if (S_ISDIR(inode->i_mode)) { | ||
| 80 | /* Don't allow creating an alias to a directory */ | ||
| 81 | struct dentry *alias = d_find_alias(inode); | ||
| 82 | if (alias) { | ||
| 83 | dput(alias); | ||
| 84 | return 1; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | static inline int invalid_nodeid(u64 nodeid) | ||
| 91 | { | ||
| 92 | return !nodeid || nodeid == FUSE_ROOT_ID; | ||
| 93 | } | ||
| 94 | |||
| 77 | static struct dentry_operations fuse_dentry_operations = { | 95 | static struct dentry_operations fuse_dentry_operations = { |
| 78 | .d_revalidate = fuse_dentry_revalidate, | 96 | .d_revalidate = fuse_dentry_revalidate, |
| 79 | }; | 97 | }; |
| @@ -97,7 +115,7 @@ static int fuse_lookup_iget(struct inode *dir, struct dentry *entry, | |||
| 97 | fuse_lookup_init(req, dir, entry, &outarg); | 115 | fuse_lookup_init(req, dir, entry, &outarg); |
| 98 | request_send(fc, req); | 116 | request_send(fc, req); |
| 99 | err = req->out.h.error; | 117 | err = req->out.h.error; |
| 100 | if (!err && (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID)) | 118 | if (!err && invalid_nodeid(outarg.nodeid)) |
| 101 | err = -EIO; | 119 | err = -EIO; |
| 102 | if (!err) { | 120 | if (!err) { |
| 103 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, | 121 | inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation, |
| @@ -193,7 +211,7 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, | |||
| 193 | } | 211 | } |
| 194 | 212 | ||
| 195 | err = -EIO; | 213 | err = -EIO; |
| 196 | if (!S_ISREG(outentry.attr.mode)) | 214 | if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid)) |
| 197 | goto out_free_ff; | 215 | goto out_free_ff; |
| 198 | 216 | ||
| 199 | inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, | 217 | inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, |
| @@ -250,7 +268,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
| 250 | fuse_put_request(fc, req); | 268 | fuse_put_request(fc, req); |
| 251 | return err; | 269 | return err; |
| 252 | } | 270 | } |
| 253 | if (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID) { | 271 | if (invalid_nodeid(outarg.nodeid)) { |
| 254 | fuse_put_request(fc, req); | 272 | fuse_put_request(fc, req); |
| 255 | return -EIO; | 273 | return -EIO; |
| 256 | } | 274 | } |
| @@ -263,7 +281,7 @@ static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, | |||
| 263 | fuse_put_request(fc, req); | 281 | fuse_put_request(fc, req); |
| 264 | 282 | ||
| 265 | /* Don't allow userspace to do really stupid things... */ | 283 | /* Don't allow userspace to do really stupid things... */ |
| 266 | if ((inode->i_mode ^ mode) & S_IFMT) { | 284 | if (((inode->i_mode ^ mode) & S_IFMT) || dir_alias(inode)) { |
| 267 | iput(inode); | 285 | iput(inode); |
| 268 | return -EIO; | 286 | return -EIO; |
| 269 | } | 287 | } |
| @@ -874,14 +892,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, | |||
| 874 | err = fuse_lookup_iget(dir, entry, &inode); | 892 | err = fuse_lookup_iget(dir, entry, &inode); |
| 875 | if (err) | 893 | if (err) |
| 876 | return ERR_PTR(err); | 894 | return ERR_PTR(err); |
| 877 | if (inode && S_ISDIR(inode->i_mode)) { | 895 | if (inode && dir_alias(inode)) { |
| 878 | /* Don't allow creating an alias to a directory */ | 896 | iput(inode); |
| 879 | struct dentry *alias = d_find_alias(inode); | 897 | return ERR_PTR(-EIO); |
| 880 | if (alias) { | ||
| 881 | dput(alias); | ||
| 882 | iput(inode); | ||
| 883 | return ERR_PTR(-EIO); | ||
| 884 | } | ||
| 885 | } | 898 | } |
| 886 | d_add(entry, inode); | 899 | d_add(entry, inode); |
| 887 | return NULL; | 900 | return NULL; |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index c60e5635498d..df16fcbff3fb 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
| @@ -151,6 +151,7 @@ struct hfsplus_sb_info { | |||
| 151 | 151 | ||
| 152 | #define HFSPLUS_SB_WRITEBACKUP 0x0001 | 152 | #define HFSPLUS_SB_WRITEBACKUP 0x0001 |
| 153 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 | 153 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 |
| 154 | #define HFSPLUS_SB_FORCE 0x0004 | ||
| 154 | 155 | ||
| 155 | 156 | ||
| 156 | struct hfsplus_inode_info { | 157 | struct hfsplus_inode_info { |
diff --git a/fs/hfsplus/hfsplus_raw.h b/fs/hfsplus/hfsplus_raw.h index 5bad37cfdb29..b4fbed633219 100644 --- a/fs/hfsplus/hfsplus_raw.h +++ b/fs/hfsplus/hfsplus_raw.h | |||
| @@ -123,11 +123,13 @@ struct hfsplus_vh { | |||
| 123 | } __packed; | 123 | } __packed; |
| 124 | 124 | ||
| 125 | /* HFS+ volume attributes */ | 125 | /* HFS+ volume attributes */ |
| 126 | #define HFSPLUS_VOL_UNMNT (1 << 8) | 126 | #define HFSPLUS_VOL_UNMNT (1 << 8) |
| 127 | #define HFSPLUS_VOL_SPARE_BLK (1 << 9) | 127 | #define HFSPLUS_VOL_SPARE_BLK (1 << 9) |
| 128 | #define HFSPLUS_VOL_NOCACHE (1 << 10) | 128 | #define HFSPLUS_VOL_NOCACHE (1 << 10) |
| 129 | #define HFSPLUS_VOL_INCNSTNT (1 << 11) | 129 | #define HFSPLUS_VOL_INCNSTNT (1 << 11) |
| 130 | #define HFSPLUS_VOL_SOFTLOCK (1 << 15) | 130 | #define HFSPLUS_VOL_NODEID_REUSED (1 << 12) |
| 131 | #define HFSPLUS_VOL_JOURNALED (1 << 13) | ||
| 132 | #define HFSPLUS_VOL_SOFTLOCK (1 << 15) | ||
| 131 | 133 | ||
| 132 | /* HFS+ BTree node descriptor */ | 134 | /* HFS+ BTree node descriptor */ |
| 133 | struct hfs_bnode_desc { | 135 | struct hfs_bnode_desc { |
diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index cca0818aa4ca..935dafba0078 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c | |||
| @@ -22,7 +22,7 @@ enum { | |||
| 22 | opt_umask, opt_uid, opt_gid, | 22 | opt_umask, opt_uid, opt_gid, |
| 23 | opt_part, opt_session, opt_nls, | 23 | opt_part, opt_session, opt_nls, |
| 24 | opt_nodecompose, opt_decompose, | 24 | opt_nodecompose, opt_decompose, |
| 25 | opt_err | 25 | opt_force, opt_err |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | static match_table_t tokens = { | 28 | static match_table_t tokens = { |
| @@ -36,6 +36,7 @@ static match_table_t tokens = { | |||
| 36 | { opt_nls, "nls=%s" }, | 36 | { opt_nls, "nls=%s" }, |
| 37 | { opt_decompose, "decompose" }, | 37 | { opt_decompose, "decompose" }, |
| 38 | { opt_nodecompose, "nodecompose" }, | 38 | { opt_nodecompose, "nodecompose" }, |
| 39 | { opt_force, "force" }, | ||
| 39 | { opt_err, NULL } | 40 | { opt_err, NULL } |
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| @@ -145,6 +146,9 @@ int hfsplus_parse_options(char *input, struct hfsplus_sb_info *sbi) | |||
| 145 | case opt_nodecompose: | 146 | case opt_nodecompose: |
| 146 | sbi->flags |= HFSPLUS_SB_NODECOMPOSE; | 147 | sbi->flags |= HFSPLUS_SB_NODECOMPOSE; |
| 147 | break; | 148 | break; |
| 149 | case opt_force: | ||
| 150 | sbi->flags |= HFSPLUS_SB_FORCE; | ||
| 151 | break; | ||
| 148 | default: | 152 | default: |
| 149 | return 0; | 153 | return 0; |
| 150 | } | 154 | } |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 0ce1c455ae55..8093351bd7c3 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
| @@ -251,16 +251,28 @@ static int hfsplus_remount(struct super_block *sb, int *flags, char *data) | |||
| 251 | return 0; | 251 | return 0; |
| 252 | if (!(*flags & MS_RDONLY)) { | 252 | if (!(*flags & MS_RDONLY)) { |
| 253 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; | 253 | struct hfsplus_vh *vhdr = HFSPLUS_SB(sb).s_vhdr; |
| 254 | struct hfsplus_sb_info sbi; | ||
| 255 | |||
| 256 | memset(&sbi, 0, sizeof(struct hfsplus_sb_info)); | ||
| 257 | sbi.nls = HFSPLUS_SB(sb).nls; | ||
| 258 | if (!hfsplus_parse_options(data, &sbi)) | ||
| 259 | return -EINVAL; | ||
| 254 | 260 | ||
| 255 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { | 261 | if (!(vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_UNMNT))) { |
| 256 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " | 262 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " |
| 257 | "running fsck.hfsplus is recommended. leaving read-only.\n"); | 263 | "running fsck.hfsplus is recommended. leaving read-only.\n"); |
| 258 | sb->s_flags |= MS_RDONLY; | 264 | sb->s_flags |= MS_RDONLY; |
| 259 | *flags |= MS_RDONLY; | 265 | *flags |= MS_RDONLY; |
| 266 | } else if (sbi.flags & HFSPLUS_SB_FORCE) { | ||
| 267 | /* nothing */ | ||
| 260 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 268 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
| 261 | printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); | 269 | printk("HFS+-fs: Filesystem is marked locked, leaving read-only.\n"); |
| 262 | sb->s_flags |= MS_RDONLY; | 270 | sb->s_flags |= MS_RDONLY; |
| 263 | *flags |= MS_RDONLY; | 271 | *flags |= MS_RDONLY; |
| 272 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { | ||
| 273 | printk("HFS+-fs: Filesystem is marked journaled, leaving read-only.\n"); | ||
| 274 | sb->s_flags |= MS_RDONLY; | ||
| 275 | *flags |= MS_RDONLY; | ||
| 264 | } | 276 | } |
| 265 | } | 277 | } |
| 266 | return 0; | 278 | return 0; |
| @@ -352,11 +364,19 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 352 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " | 364 | printk("HFS+-fs warning: Filesystem was not cleanly unmounted, " |
| 353 | "running fsck.hfsplus is recommended. mounting read-only.\n"); | 365 | "running fsck.hfsplus is recommended. mounting read-only.\n"); |
| 354 | sb->s_flags |= MS_RDONLY; | 366 | sb->s_flags |= MS_RDONLY; |
| 367 | } else if (sbi->flags & HFSPLUS_SB_FORCE) { | ||
| 368 | /* nothing */ | ||
| 355 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { | 369 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_SOFTLOCK)) { |
| 356 | if (!silent) | 370 | if (!silent) |
| 357 | printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); | 371 | printk("HFS+-fs: Filesystem is marked locked, mounting read-only.\n"); |
| 358 | sb->s_flags |= MS_RDONLY; | 372 | sb->s_flags |= MS_RDONLY; |
| 373 | } else if (vhdr->attributes & cpu_to_be32(HFSPLUS_VOL_JOURNALED)) { | ||
| 374 | if (!silent) | ||
| 375 | printk("HFS+-fs: write access to a jounaled filesystem is not supported, " | ||
| 376 | "use the force option at your own risk, mounting read-only.\n"); | ||
| 377 | sb->s_flags |= MS_RDONLY; | ||
| 359 | } | 378 | } |
| 379 | sbi->flags &= ~HFSPLUS_SB_FORCE; | ||
| 360 | 380 | ||
| 361 | /* Load metadata objects (B*Trees) */ | 381 | /* Load metadata objects (B*Trees) */ |
| 362 | HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); | 382 | HFSPLUS_SB(sb).ext_tree = hfs_btree_open(sb, HFSPLUS_EXT_CNID); |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 543420665c5b..d0fcc5f3497e 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
| @@ -234,6 +234,7 @@ void jffs2_read_inode (struct inode *inode) | |||
| 234 | c = JFFS2_SB_INFO(inode->i_sb); | 234 | c = JFFS2_SB_INFO(inode->i_sb); |
| 235 | 235 | ||
| 236 | jffs2_init_inode_info(f); | 236 | jffs2_init_inode_info(f); |
| 237 | down(&f->sem); | ||
| 237 | 238 | ||
| 238 | ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); | 239 | ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); |
| 239 | 240 | ||
| @@ -400,6 +401,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i | |||
| 400 | 401 | ||
| 401 | f = JFFS2_INODE_INFO(inode); | 402 | f = JFFS2_INODE_INFO(inode); |
| 402 | jffs2_init_inode_info(f); | 403 | jffs2_init_inode_info(f); |
| 404 | down(&f->sem); | ||
| 403 | 405 | ||
| 404 | memset(ri, 0, sizeof(*ri)); | 406 | memset(ri, 0, sizeof(*ri)); |
| 405 | /* Set OS-specific defaults for new inodes */ | 407 | /* Set OS-specific defaults for new inodes */ |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 9e0b5458d9c0..93883817cbd0 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
| @@ -51,7 +51,7 @@ static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long f | |||
| 51 | 51 | ||
| 52 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | 52 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == |
| 53 | SLAB_CTOR_CONSTRUCTOR) { | 53 | SLAB_CTOR_CONSTRUCTOR) { |
| 54 | init_MUTEX_LOCKED(&ei->sem); | 54 | init_MUTEX(&ei->sem); |
| 55 | inode_init_once(&ei->vfs_inode); | 55 | inode_init_once(&ei->vfs_inode); |
| 56 | } | 56 | } |
| 57 | } | 57 | } |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 7370583b61e5..c0d1a214572c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1287,6 +1287,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name); | |||
| 1287 | nfs_begin_data_update(dentry->d_inode); | 1287 | nfs_begin_data_update(dentry->d_inode); |
| 1288 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | 1288 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, |
| 1289 | dir, &qsilly); | 1289 | dir, &qsilly); |
| 1290 | nfs_mark_for_revalidate(dentry->d_inode); | ||
| 1290 | nfs_end_data_update(dentry->d_inode); | 1291 | nfs_end_data_update(dentry->d_inode); |
| 1291 | } else | 1292 | } else |
| 1292 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | 1293 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, |
| @@ -1334,6 +1335,7 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
| 1334 | /* The VFS may want to delete this inode */ | 1335 | /* The VFS may want to delete this inode */ |
| 1335 | if (error == 0) | 1336 | if (error == 0) |
| 1336 | inode->i_nlink--; | 1337 | inode->i_nlink--; |
| 1338 | nfs_mark_for_revalidate(inode); | ||
| 1337 | nfs_end_data_update(inode); | 1339 | nfs_end_data_update(inode); |
| 1338 | } else | 1340 | } else |
| 1339 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1341 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
| @@ -1556,6 +1558,7 @@ go_ahead: | |||
| 1556 | nfs_begin_data_update(old_inode); | 1558 | nfs_begin_data_update(old_inode); |
| 1557 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, | 1559 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, |
| 1558 | new_dir, &new_dentry->d_name); | 1560 | new_dir, &new_dentry->d_name); |
| 1561 | nfs_mark_for_revalidate(old_inode); | ||
| 1559 | nfs_end_data_update(old_inode); | 1562 | nfs_end_data_update(old_inode); |
| 1560 | nfs_end_data_update(new_dir); | 1563 | nfs_end_data_update(new_dir); |
| 1561 | nfs_end_data_update(old_dir); | 1564 | nfs_end_data_update(old_dir); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6391d8964214..afd75d0463fd 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -54,7 +54,7 @@ | |||
| 54 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) | 54 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) |
| 55 | 55 | ||
| 56 | static void nfs_invalidate_inode(struct inode *); | 56 | static void nfs_invalidate_inode(struct inode *); |
| 57 | static int nfs_update_inode(struct inode *, struct nfs_fattr *, unsigned long); | 57 | static int nfs_update_inode(struct inode *, struct nfs_fattr *); |
| 58 | 58 | ||
| 59 | static struct inode *nfs_alloc_inode(struct super_block *sb); | 59 | static struct inode *nfs_alloc_inode(struct super_block *sb); |
| 60 | static void nfs_destroy_inode(struct inode *); | 60 | static void nfs_destroy_inode(struct inode *); |
| @@ -643,14 +643,11 @@ static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
| 643 | /* | 643 | /* |
| 644 | * Invalidate the local caches | 644 | * Invalidate the local caches |
| 645 | */ | 645 | */ |
| 646 | void | 646 | static void nfs_zap_caches_locked(struct inode *inode) |
| 647 | nfs_zap_caches(struct inode *inode) | ||
| 648 | { | 647 | { |
| 649 | struct nfs_inode *nfsi = NFS_I(inode); | 648 | struct nfs_inode *nfsi = NFS_I(inode); |
| 650 | int mode = inode->i_mode; | 649 | int mode = inode->i_mode; |
| 651 | 650 | ||
| 652 | spin_lock(&inode->i_lock); | ||
| 653 | |||
| 654 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); | 651 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); |
| 655 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; | 652 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; |
| 656 | 653 | ||
| @@ -659,7 +656,12 @@ nfs_zap_caches(struct inode *inode) | |||
| 659 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 656 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; |
| 660 | else | 657 | else |
| 661 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 658 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; |
| 659 | } | ||
| 662 | 660 | ||
| 661 | void nfs_zap_caches(struct inode *inode) | ||
| 662 | { | ||
| 663 | spin_lock(&inode->i_lock); | ||
| 664 | nfs_zap_caches_locked(inode); | ||
| 663 | spin_unlock(&inode->i_lock); | 665 | spin_unlock(&inode->i_lock); |
| 664 | } | 666 | } |
| 665 | 667 | ||
| @@ -676,16 +678,13 @@ static void nfs_zap_acl_cache(struct inode *inode) | |||
| 676 | } | 678 | } |
| 677 | 679 | ||
| 678 | /* | 680 | /* |
| 679 | * Invalidate, but do not unhash, the inode | 681 | * Invalidate, but do not unhash, the inode. |
| 682 | * NB: must be called with inode->i_lock held! | ||
| 680 | */ | 683 | */ |
| 681 | static void | 684 | static void nfs_invalidate_inode(struct inode *inode) |
| 682 | nfs_invalidate_inode(struct inode *inode) | ||
| 683 | { | 685 | { |
| 684 | umode_t save_mode = inode->i_mode; | 686 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
| 685 | 687 | nfs_zap_caches_locked(inode); | |
| 686 | make_bad_inode(inode); | ||
| 687 | inode->i_mode = save_mode; | ||
| 688 | nfs_zap_caches(inode); | ||
| 689 | } | 688 | } |
| 690 | 689 | ||
| 691 | struct nfs_find_desc { | 690 | struct nfs_find_desc { |
| @@ -1081,8 +1080,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 1081 | int status = -ESTALE; | 1080 | int status = -ESTALE; |
| 1082 | struct nfs_fattr fattr; | 1081 | struct nfs_fattr fattr; |
| 1083 | struct nfs_inode *nfsi = NFS_I(inode); | 1082 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1084 | unsigned long verifier; | ||
| 1085 | unsigned long cache_validity; | ||
| 1086 | 1083 | ||
| 1087 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 1084 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
| 1088 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 1085 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
| @@ -1107,8 +1104,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 1107 | } | 1104 | } |
| 1108 | } | 1105 | } |
| 1109 | 1106 | ||
| 1110 | /* Protect against RPC races by saving the change attribute */ | ||
| 1111 | verifier = nfs_save_change_attribute(inode); | ||
| 1112 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 1107 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
| 1113 | if (status != 0) { | 1108 | if (status != 0) { |
| 1114 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 1109 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
| @@ -1123,7 +1118,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 1123 | } | 1118 | } |
| 1124 | 1119 | ||
| 1125 | spin_lock(&inode->i_lock); | 1120 | spin_lock(&inode->i_lock); |
| 1126 | status = nfs_update_inode(inode, &fattr, verifier); | 1121 | status = nfs_update_inode(inode, &fattr); |
| 1127 | if (status) { | 1122 | if (status) { |
| 1128 | spin_unlock(&inode->i_lock); | 1123 | spin_unlock(&inode->i_lock); |
| 1129 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 1124 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
| @@ -1131,20 +1126,11 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
| 1131 | (long long)NFS_FILEID(inode), status); | 1126 | (long long)NFS_FILEID(inode), status); |
| 1132 | goto out; | 1127 | goto out; |
| 1133 | } | 1128 | } |
| 1134 | cache_validity = nfsi->cache_validity; | ||
| 1135 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | ||
| 1136 | |||
| 1137 | /* | ||
| 1138 | * We may need to keep the attributes marked as invalid if | ||
| 1139 | * we raced with nfs_end_attr_update(). | ||
| 1140 | */ | ||
| 1141 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) | ||
| 1142 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
| 1143 | spin_unlock(&inode->i_lock); | 1129 | spin_unlock(&inode->i_lock); |
| 1144 | 1130 | ||
| 1145 | nfs_revalidate_mapping(inode, inode->i_mapping); | 1131 | nfs_revalidate_mapping(inode, inode->i_mapping); |
| 1146 | 1132 | ||
| 1147 | if (cache_validity & NFS_INO_INVALID_ACL) | 1133 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) |
| 1148 | nfs_zap_acl_cache(inode); | 1134 | nfs_zap_acl_cache(inode); |
| 1149 | 1135 | ||
| 1150 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", | 1136 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", |
| @@ -1347,10 +1333,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1347 | return 0; | 1333 | return 0; |
| 1348 | spin_lock(&inode->i_lock); | 1334 | spin_lock(&inode->i_lock); |
| 1349 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | 1335 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; |
| 1350 | if (nfs_verify_change_attribute(inode, fattr->time_start)) | ||
| 1351 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
| 1352 | if (time_after(fattr->time_start, nfsi->last_updated)) | 1336 | if (time_after(fattr->time_start, nfsi->last_updated)) |
| 1353 | status = nfs_update_inode(inode, fattr, fattr->time_start); | 1337 | status = nfs_update_inode(inode, fattr); |
| 1354 | else | 1338 | else |
| 1355 | status = nfs_check_inode_attributes(inode, fattr); | 1339 | status = nfs_check_inode_attributes(inode, fattr); |
| 1356 | 1340 | ||
| @@ -1376,10 +1360,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1376 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; | 1360 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; |
| 1377 | goto out; | 1361 | goto out; |
| 1378 | } | 1362 | } |
| 1379 | status = nfs_update_inode(inode, fattr, fattr->time_start); | 1363 | status = nfs_update_inode(inode, fattr); |
| 1380 | if (time_after_eq(fattr->time_start, nfsi->cache_change_attribute)) | ||
| 1381 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | ||
| 1382 | nfsi->cache_change_attribute = jiffies; | ||
| 1383 | out: | 1364 | out: |
| 1384 | spin_unlock(&inode->i_lock); | 1365 | spin_unlock(&inode->i_lock); |
| 1385 | return status; | 1366 | return status; |
| @@ -1397,12 +1378,12 @@ out: | |||
| 1397 | * | 1378 | * |
| 1398 | * A very similar scenario holds for the dir cache. | 1379 | * A very similar scenario holds for the dir cache. |
| 1399 | */ | 1380 | */ |
| 1400 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) | 1381 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 1401 | { | 1382 | { |
| 1402 | struct nfs_inode *nfsi = NFS_I(inode); | 1383 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1403 | loff_t cur_isize, new_isize; | 1384 | loff_t cur_isize, new_isize; |
| 1404 | unsigned int invalid = 0; | 1385 | unsigned int invalid = 0; |
| 1405 | int data_unstable; | 1386 | int data_stable; |
| 1406 | 1387 | ||
| 1407 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", | 1388 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", |
| 1408 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, | 1389 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, |
| @@ -1433,8 +1414,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1433 | nfsi->last_updated = jiffies; | 1414 | nfsi->last_updated = jiffies; |
| 1434 | 1415 | ||
| 1435 | /* Are we racing with known updates of the metadata on the server? */ | 1416 | /* Are we racing with known updates of the metadata on the server? */ |
| 1436 | data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || | 1417 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); |
| 1437 | (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)); | 1418 | if (data_stable) |
| 1419 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
| 1438 | 1420 | ||
| 1439 | /* Check if our cached file size is stale */ | 1421 | /* Check if our cached file size is stale */ |
| 1440 | new_isize = nfs_size_to_loff_t(fattr->size); | 1422 | new_isize = nfs_size_to_loff_t(fattr->size); |
| @@ -1443,7 +1425,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1443 | /* Do we perhaps have any outstanding writes? */ | 1425 | /* Do we perhaps have any outstanding writes? */ |
| 1444 | if (nfsi->npages == 0) { | 1426 | if (nfsi->npages == 0) { |
| 1445 | /* No, but did we race with nfs_end_data_update()? */ | 1427 | /* No, but did we race with nfs_end_data_update()? */ |
| 1446 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) { | 1428 | if (data_stable) { |
| 1447 | inode->i_size = new_isize; | 1429 | inode->i_size = new_isize; |
| 1448 | invalid |= NFS_INO_INVALID_DATA; | 1430 | invalid |= NFS_INO_INVALID_DATA; |
| 1449 | } | 1431 | } |
| @@ -1452,6 +1434,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1452 | inode->i_size = new_isize; | 1434 | inode->i_size = new_isize; |
| 1453 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1435 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
| 1454 | } | 1436 | } |
| 1437 | nfsi->cache_change_attribute = jiffies; | ||
| 1455 | dprintk("NFS: isize change on server for file %s/%ld\n", | 1438 | dprintk("NFS: isize change on server for file %s/%ld\n", |
| 1456 | inode->i_sb->s_id, inode->i_ino); | 1439 | inode->i_sb->s_id, inode->i_ino); |
| 1457 | } | 1440 | } |
| @@ -1461,8 +1444,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1461 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1444 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
| 1462 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1445 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
| 1463 | inode->i_sb->s_id, inode->i_ino); | 1446 | inode->i_sb->s_id, inode->i_ino); |
| 1464 | if (!data_unstable) | 1447 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
| 1465 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1448 | nfsi->cache_change_attribute = jiffies; |
| 1466 | } | 1449 | } |
| 1467 | 1450 | ||
| 1468 | if ((fattr->valid & NFS_ATTR_FATTR_V4) | 1451 | if ((fattr->valid & NFS_ATTR_FATTR_V4) |
| @@ -1470,15 +1453,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1470 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1453 | dprintk("NFS: change_attr change on server for file %s/%ld\n", |
| 1471 | inode->i_sb->s_id, inode->i_ino); | 1454 | inode->i_sb->s_id, inode->i_ino); |
| 1472 | nfsi->change_attr = fattr->change_attr; | 1455 | nfsi->change_attr = fattr->change_attr; |
| 1473 | if (!data_unstable) | 1456 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
| 1474 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1457 | nfsi->cache_change_attribute = jiffies; |
| 1475 | } | 1458 | } |
| 1476 | 1459 | ||
| 1477 | /* If ctime has changed we should definitely clear access+acl caches */ | 1460 | /* If ctime has changed we should definitely clear access+acl caches */ |
| 1478 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1461 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
| 1479 | if (!data_unstable) | 1462 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
| 1480 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
| 1481 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1463 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
| 1464 | nfsi->cache_change_attribute = jiffies; | ||
| 1482 | } | 1465 | } |
| 1483 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | 1466 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
| 1484 | 1467 | ||
| @@ -1516,6 +1499,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1516 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1499 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
| 1517 | || S_ISLNK(inode->i_mode))) | 1500 | || S_ISLNK(inode->i_mode))) |
| 1518 | invalid &= ~NFS_INO_INVALID_DATA; | 1501 | invalid &= ~NFS_INO_INVALID_DATA; |
| 1502 | if (data_stable) | ||
| 1503 | invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | ||
| 1519 | if (!nfs_have_delegation(inode, FMODE_READ)) | 1504 | if (!nfs_have_delegation(inode, FMODE_READ)) |
| 1520 | nfsi->cache_validity |= invalid; | 1505 | nfsi->cache_validity |= invalid; |
| 1521 | 1506 | ||
| @@ -1528,14 +1513,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
| 1528 | printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n", | 1513 | printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n", |
| 1529 | __FUNCTION__, inode->i_ino, inode->i_mode, fattr->mode); | 1514 | __FUNCTION__, inode->i_ino, inode->i_mode, fattr->mode); |
| 1530 | #endif | 1515 | #endif |
| 1516 | out_err: | ||
| 1531 | /* | 1517 | /* |
| 1532 | * No need to worry about unhashing the dentry, as the | 1518 | * No need to worry about unhashing the dentry, as the |
| 1533 | * lookup validation will know that the inode is bad. | 1519 | * lookup validation will know that the inode is bad. |
| 1534 | * (But we fall through to invalidate the caches.) | 1520 | * (But we fall through to invalidate the caches.) |
| 1535 | */ | 1521 | */ |
| 1536 | nfs_invalidate_inode(inode); | 1522 | nfs_invalidate_inode(inode); |
| 1537 | out_err: | ||
| 1538 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); | ||
| 1539 | return -ESTALE; | 1523 | return -ESTALE; |
| 1540 | } | 1524 | } |
| 1541 | 1525 | ||
| @@ -2068,6 +2052,7 @@ static struct inode *nfs_alloc_inode(struct super_block *sb) | |||
| 2068 | return NULL; | 2052 | return NULL; |
| 2069 | nfsi->flags = 0UL; | 2053 | nfsi->flags = 0UL; |
| 2070 | nfsi->cache_validity = 0UL; | 2054 | nfsi->cache_validity = 0UL; |
| 2055 | nfsi->cache_change_attribute = jiffies; | ||
| 2071 | #ifdef CONFIG_NFS_V3_ACL | 2056 | #ifdef CONFIG_NFS_V3_ACL |
| 2072 | nfsi->acl_access = ERR_PTR(-EAGAIN); | 2057 | nfsi->acl_access = ERR_PTR(-EAGAIN); |
| 2073 | nfsi->acl_default = ERR_PTR(-EAGAIN); | 2058 | nfsi->acl_default = ERR_PTR(-EAGAIN); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 21482b2518f6..f988a9417b13 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -1506,10 +1506,15 @@ static int _nfs4_proc_write(struct nfs_write_data *wdata) | |||
| 1506 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | 1506 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, |
| 1507 | (long long) wdata->args.offset); | 1507 | (long long) wdata->args.offset); |
| 1508 | 1508 | ||
| 1509 | wdata->args.bitmask = server->attr_bitmask; | ||
| 1510 | wdata->res.server = server; | ||
| 1509 | nfs_fattr_init(fattr); | 1511 | nfs_fattr_init(fattr); |
| 1510 | status = rpc_call_sync(server->client, &msg, rpcflags); | 1512 | status = rpc_call_sync(server->client, &msg, rpcflags); |
| 1511 | dprintk("NFS reply write: %d\n", status); | 1513 | dprintk("NFS reply write: %d\n", status); |
| 1512 | return status; | 1514 | if (status < 0) |
| 1515 | return status; | ||
| 1516 | nfs_post_op_update_inode(inode, fattr); | ||
| 1517 | return wdata->res.count; | ||
| 1513 | } | 1518 | } |
| 1514 | 1519 | ||
| 1515 | static int nfs4_proc_write(struct nfs_write_data *wdata) | 1520 | static int nfs4_proc_write(struct nfs_write_data *wdata) |
| @@ -1540,9 +1545,13 @@ static int _nfs4_proc_commit(struct nfs_write_data *cdata) | |||
| 1540 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, | 1545 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, |
| 1541 | (long long) cdata->args.offset); | 1546 | (long long) cdata->args.offset); |
| 1542 | 1547 | ||
| 1548 | cdata->args.bitmask = server->attr_bitmask; | ||
| 1549 | cdata->res.server = server; | ||
| 1543 | nfs_fattr_init(fattr); | 1550 | nfs_fattr_init(fattr); |
| 1544 | status = rpc_call_sync(server->client, &msg, 0); | 1551 | status = rpc_call_sync(server->client, &msg, 0); |
| 1545 | dprintk("NFS reply commit: %d\n", status); | 1552 | dprintk("NFS reply commit: %d\n", status); |
| 1553 | if (status >= 0) | ||
| 1554 | nfs_post_op_update_inode(inode, fattr); | ||
| 1546 | return status; | 1555 | return status; |
| 1547 | } | 1556 | } |
| 1548 | 1557 | ||
| @@ -3071,15 +3080,15 @@ static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock | |||
| 3071 | struct nfs4_client *clp = state->owner->so_client; | 3080 | struct nfs4_client *clp = state->owner->so_client; |
| 3072 | int status; | 3081 | int status; |
| 3073 | 3082 | ||
| 3074 | down_read(&clp->cl_sem); | ||
| 3075 | /* Is this a delegated open? */ | 3083 | /* Is this a delegated open? */ |
| 3076 | if (test_bit(NFS_DELEGATED_STATE, &state->flags)) { | 3084 | if (NFS_I(state->inode)->delegation_state != 0) { |
| 3077 | /* Yes: cache locks! */ | 3085 | /* Yes: cache locks! */ |
| 3078 | status = do_vfs_lock(request->fl_file, request); | 3086 | status = do_vfs_lock(request->fl_file, request); |
| 3079 | /* ...but avoid races with delegation recall... */ | 3087 | /* ...but avoid races with delegation recall... */ |
| 3080 | if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags)) | 3088 | if (status < 0 || test_bit(NFS_DELEGATED_STATE, &state->flags)) |
| 3081 | goto out; | 3089 | return status; |
| 3082 | } | 3090 | } |
| 3091 | down_read(&clp->cl_sem); | ||
| 3083 | status = nfs4_set_lock_state(state, request); | 3092 | status = nfs4_set_lock_state(state, request); |
| 3084 | if (status != 0) | 3093 | if (status != 0) |
| 3085 | goto out; | 3094 | goto out; |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 0675f3215e0a..5ef4c57618fe 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
| @@ -644,12 +644,15 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
| 644 | 644 | ||
| 645 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) | 645 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter) |
| 646 | { | 646 | { |
| 647 | struct rpc_sequence *sequence = counter->sequence; | ||
| 647 | struct nfs_seqid *new; | 648 | struct nfs_seqid *new; |
| 648 | 649 | ||
| 649 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 650 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
| 650 | if (new != NULL) { | 651 | if (new != NULL) { |
| 651 | new->sequence = counter; | 652 | new->sequence = counter; |
| 652 | INIT_LIST_HEAD(&new->list); | 653 | spin_lock(&sequence->lock); |
| 654 | list_add_tail(&new->list, &sequence->list); | ||
| 655 | spin_unlock(&sequence->lock); | ||
| 653 | } | 656 | } |
| 654 | return new; | 657 | return new; |
| 655 | } | 658 | } |
| @@ -658,12 +661,10 @@ void nfs_free_seqid(struct nfs_seqid *seqid) | |||
| 658 | { | 661 | { |
| 659 | struct rpc_sequence *sequence = seqid->sequence->sequence; | 662 | struct rpc_sequence *sequence = seqid->sequence->sequence; |
| 660 | 663 | ||
| 661 | if (!list_empty(&seqid->list)) { | 664 | spin_lock(&sequence->lock); |
| 662 | spin_lock(&sequence->lock); | 665 | list_del(&seqid->list); |
| 663 | list_del(&seqid->list); | 666 | spin_unlock(&sequence->lock); |
| 664 | spin_unlock(&sequence->lock); | 667 | rpc_wake_up(&sequence->wait); |
| 665 | } | ||
| 666 | rpc_wake_up_next(&sequence->wait); | ||
| 667 | kfree(seqid); | 668 | kfree(seqid); |
| 668 | } | 669 | } |
| 669 | 670 | ||
| @@ -722,11 +723,10 @@ int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task) | |||
| 722 | if (sequence->list.next == &seqid->list) | 723 | if (sequence->list.next == &seqid->list) |
| 723 | goto out; | 724 | goto out; |
| 724 | spin_lock(&sequence->lock); | 725 | spin_lock(&sequence->lock); |
| 725 | if (!list_empty(&sequence->list)) { | 726 | if (sequence->list.next != &seqid->list) { |
| 726 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); | 727 | rpc_sleep_on(&sequence->wait, task, NULL, NULL); |
| 727 | status = -EAGAIN; | 728 | status = -EAGAIN; |
| 728 | } else | 729 | } |
| 729 | list_add(&seqid->list, &sequence->list); | ||
| 730 | spin_unlock(&sequence->lock); | 730 | spin_unlock(&sequence->lock); |
| 731 | out: | 731 | out: |
| 732 | return status; | 732 | return status; |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index a48a003242c0..e1e3ca5d746b 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
| @@ -375,6 +375,7 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | |||
| 375 | 375 | ||
| 376 | dprintk("NFS call link %s\n", name->name); | 376 | dprintk("NFS call link %s\n", name->name); |
| 377 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0); | 377 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0); |
| 378 | nfs_mark_for_revalidate(inode); | ||
| 378 | nfs_mark_for_revalidate(dir); | 379 | nfs_mark_for_revalidate(dir); |
| 379 | dprintk("NFS reply link: %d\n", status); | 380 | dprintk("NFS reply link: %d\n", status); |
| 380 | return status; | 381 | return status; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 8f71e766cc5d..3107908e5f3f 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
| @@ -189,6 +189,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode, | |||
| 189 | (long long)NFS_FILEID(inode), | 189 | (long long)NFS_FILEID(inode), |
| 190 | count, (long long)(page_offset(page) + offset)); | 190 | count, (long long)(page_offset(page) + offset)); |
| 191 | 191 | ||
| 192 | set_page_writeback(page); | ||
| 192 | nfs_begin_data_update(inode); | 193 | nfs_begin_data_update(inode); |
| 193 | do { | 194 | do { |
| 194 | if (count < wsize) | 195 | if (count < wsize) |
| @@ -221,6 +222,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode, | |||
| 221 | 222 | ||
| 222 | io_error: | 223 | io_error: |
| 223 | nfs_end_data_update(inode); | 224 | nfs_end_data_update(inode); |
| 225 | end_page_writeback(page); | ||
| 224 | nfs_writedata_free(wdata); | 226 | nfs_writedata_free(wdata); |
| 225 | return written ? written : result; | 227 | return written ? written : result; |
| 226 | } | 228 | } |
| @@ -929,7 +931,7 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how) | |||
| 929 | atomic_set(&req->wb_complete, requests); | 931 | atomic_set(&req->wb_complete, requests); |
| 930 | 932 | ||
| 931 | ClearPageError(page); | 933 | ClearPageError(page); |
| 932 | SetPageWriteback(page); | 934 | set_page_writeback(page); |
| 933 | offset = 0; | 935 | offset = 0; |
| 934 | nbytes = req->wb_bytes; | 936 | nbytes = req->wb_bytes; |
| 935 | do { | 937 | do { |
| @@ -992,7 +994,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how) | |||
| 992 | nfs_list_remove_request(req); | 994 | nfs_list_remove_request(req); |
| 993 | nfs_list_add_request(req, &data->pages); | 995 | nfs_list_add_request(req, &data->pages); |
| 994 | ClearPageError(req->wb_page); | 996 | ClearPageError(req->wb_page); |
| 995 | SetPageWriteback(req->wb_page); | 997 | set_page_writeback(req->wb_page); |
| 996 | *pages++ = req->wb_page; | 998 | *pages++ = req->wb_page; |
| 997 | count += req->wb_bytes; | 999 | count += req->wb_bytes; |
| 998 | } | 1000 | } |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 9ab97cef0daa..50bd5a8f0446 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -402,12 +402,11 @@ struct numa_maps { | |||
| 402 | /* | 402 | /* |
| 403 | * Calculate numa node maps for a vma | 403 | * Calculate numa node maps for a vma |
| 404 | */ | 404 | */ |
| 405 | static struct numa_maps *get_numa_maps(const struct vm_area_struct *vma) | 405 | static struct numa_maps *get_numa_maps(struct vm_area_struct *vma) |
| 406 | { | 406 | { |
| 407 | int i; | ||
| 407 | struct page *page; | 408 | struct page *page; |
| 408 | unsigned long vaddr; | 409 | unsigned long vaddr; |
| 409 | struct mm_struct *mm = vma->vm_mm; | ||
| 410 | int i; | ||
| 411 | struct numa_maps *md = kmalloc(sizeof(struct numa_maps), GFP_KERNEL); | 410 | struct numa_maps *md = kmalloc(sizeof(struct numa_maps), GFP_KERNEL); |
| 412 | 411 | ||
| 413 | if (!md) | 412 | if (!md) |
| @@ -420,7 +419,7 @@ static struct numa_maps *get_numa_maps(const struct vm_area_struct *vma) | |||
| 420 | md->node[i] =0; | 419 | md->node[i] =0; |
| 421 | 420 | ||
| 422 | for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) { | 421 | for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) { |
| 423 | page = follow_page(mm, vaddr, 0); | 422 | page = follow_page(vma, vaddr, 0); |
| 424 | if (page) { | 423 | if (page) { |
| 425 | int count = page_mapcount(page); | 424 | int count = page_mapcount(page); |
| 426 | 425 | ||
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 5f82352b97e1..0a044ad98885 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c | |||
| @@ -2194,7 +2194,7 @@ static int map_block_for_writepage(struct inode *inode, | |||
| 2194 | INITIALIZE_PATH(path); | 2194 | INITIALIZE_PATH(path); |
| 2195 | int pos_in_item; | 2195 | int pos_in_item; |
| 2196 | int jbegin_count = JOURNAL_PER_BALANCE_CNT; | 2196 | int jbegin_count = JOURNAL_PER_BALANCE_CNT; |
| 2197 | loff_t byte_offset = (block << inode->i_sb->s_blocksize_bits) + 1; | 2197 | loff_t byte_offset = ((loff_t)block << inode->i_sb->s_blocksize_bits)+1; |
| 2198 | int retval; | 2198 | int retval; |
| 2199 | int use_get_block = 0; | 2199 | int use_get_block = 0; |
| 2200 | int bytes_copied = 0; | 2200 | int bytes_copied = 0; |
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 4b15761434bc..68b7b78638ff 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c | |||
| @@ -2757,6 +2757,15 @@ int journal_init(struct super_block *p_s_sb, const char *j_dev_name, | |||
| 2757 | journal->j_cnode_used = 0; | 2757 | journal->j_cnode_used = 0; |
| 2758 | journal->j_must_wait = 0; | 2758 | journal->j_must_wait = 0; |
| 2759 | 2759 | ||
| 2760 | if (journal->j_cnode_free == 0) { | ||
| 2761 | reiserfs_warning(p_s_sb, "journal-2004: Journal cnode memory " | ||
| 2762 | "allocation failed (%ld bytes). Journal is " | ||
| 2763 | "too large for available memory. Usually " | ||
| 2764 | "this is due to a journal that is too large.", | ||
| 2765 | sizeof (struct reiserfs_journal_cnode) * num_cnodes); | ||
| 2766 | goto free_and_return; | ||
| 2767 | } | ||
| 2768 | |||
| 2760 | init_journal_hash(p_s_sb); | 2769 | init_journal_hash(p_s_sb); |
| 2761 | jl = journal->j_current_jl; | 2770 | jl = journal->j_current_jl; |
| 2762 | jl->j_list_bitmap = get_list_bitmap(p_s_sb, jl); | 2771 | jl->j_list_bitmap = get_list_bitmap(p_s_sb, jl); |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c6108971b4e6..94d3cdfbf9b8 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
| @@ -941,13 +941,12 @@ __linvfs_get_block( | |||
| 941 | int retpbbm = 1; | 941 | int retpbbm = 1; |
| 942 | int error; | 942 | int error; |
| 943 | 943 | ||
| 944 | if (blocks) { | ||
| 945 | offset = blocks << inode->i_blkbits; /* 64 bit goodness */ | ||
| 946 | size = (ssize_t) min_t(xfs_off_t, offset, LONG_MAX); | ||
| 947 | } else { | ||
| 948 | size = 1 << inode->i_blkbits; | ||
| 949 | } | ||
| 950 | offset = (xfs_off_t)iblock << inode->i_blkbits; | 944 | offset = (xfs_off_t)iblock << inode->i_blkbits; |
| 945 | if (blocks) | ||
| 946 | size = (ssize_t) min_t(xfs_off_t, LONG_MAX, | ||
| 947 | (xfs_off_t)blocks << inode->i_blkbits); | ||
| 948 | else | ||
| 949 | size = 1 << inode->i_blkbits; | ||
| 951 | 950 | ||
| 952 | VOP_BMAP(vp, offset, size, | 951 | VOP_BMAP(vp, offset, size, |
| 953 | create ? flags : BMAPI_READ, &iomap, &retpbbm, error); | 952 | create ? flags : BMAPI_READ, &iomap, &retpbbm, error); |
| @@ -1007,7 +1006,7 @@ __linvfs_get_block( | |||
| 1007 | ASSERT(iomap.iomap_bsize - iomap.iomap_delta > 0); | 1006 | ASSERT(iomap.iomap_bsize - iomap.iomap_delta > 0); |
| 1008 | offset = min_t(xfs_off_t, | 1007 | offset = min_t(xfs_off_t, |
| 1009 | iomap.iomap_bsize - iomap.iomap_delta, | 1008 | iomap.iomap_bsize - iomap.iomap_delta, |
| 1010 | blocks << inode->i_blkbits); | 1009 | (xfs_off_t)blocks << inode->i_blkbits); |
| 1011 | bh_result->b_size = (u32) min_t(xfs_off_t, UINT_MAX, offset); | 1010 | bh_result->b_size = (u32) min_t(xfs_off_t, UINT_MAX, offset); |
| 1012 | } | 1011 | } |
| 1013 | 1012 | ||
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 35e557b00db2..1c7421840c18 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
| @@ -310,7 +310,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
| 310 | * Fix up the start offset of the attribute fork | 310 | * Fix up the start offset of the attribute fork |
| 311 | */ | 311 | */ |
| 312 | totsize -= size; | 312 | totsize -= size; |
| 313 | if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname) { | 313 | if (totsize == sizeof(xfs_attr_sf_hdr_t) && !args->addname && |
| 314 | !(mp->m_flags & XFS_MOUNT_COMPAT_ATTR)) { | ||
| 314 | /* | 315 | /* |
| 315 | * Last attribute now removed, revert to original | 316 | * Last attribute now removed, revert to original |
| 316 | * inode format making all literal area available | 317 | * inode format making all literal area available |
| @@ -328,7 +329,8 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
| 328 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); | 329 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); |
| 329 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); | 330 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); |
| 330 | ASSERT(dp->i_d.di_forkoff); | 331 | ASSERT(dp->i_d.di_forkoff); |
| 331 | ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname); | 332 | ASSERT(totsize > sizeof(xfs_attr_sf_hdr_t) || args->addname || |
| 333 | (mp->m_flags & XFS_MOUNT_COMPAT_ATTR)); | ||
| 332 | dp->i_afp->if_ext_max = | 334 | dp->i_afp->if_ext_max = |
| 333 | XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | 335 | XFS_IFORK_ASIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); |
| 334 | dp->i_df.if_ext_max = | 336 | dp->i_df.if_ext_max = |
| @@ -737,7 +739,8 @@ xfs_attr_shortform_allfit(xfs_dabuf_t *bp, xfs_inode_t *dp) | |||
| 737 | + name_loc->namelen | 739 | + name_loc->namelen |
| 738 | + INT_GET(name_loc->valuelen, ARCH_CONVERT); | 740 | + INT_GET(name_loc->valuelen, ARCH_CONVERT); |
| 739 | } | 741 | } |
| 740 | if (bytes == sizeof(struct xfs_attr_sf_hdr)) | 742 | if (!(dp->i_mount->m_flags & XFS_MOUNT_COMPAT_ATTR) && |
| 743 | (bytes == sizeof(struct xfs_attr_sf_hdr))) | ||
| 741 | return(-1); | 744 | return(-1); |
| 742 | return(xfs_attr_shortform_bytesfit(dp, bytes)); | 745 | return(xfs_attr_shortform_bytesfit(dp, bytes)); |
| 743 | } | 746 | } |
| @@ -775,6 +778,8 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) | |||
| 775 | goto out; | 778 | goto out; |
| 776 | 779 | ||
| 777 | if (forkoff == -1) { | 780 | if (forkoff == -1) { |
| 781 | ASSERT(!(dp->i_mount->m_flags & XFS_MOUNT_COMPAT_ATTR)); | ||
| 782 | |||
| 778 | /* | 783 | /* |
| 779 | * Last attribute was removed, revert to original | 784 | * Last attribute was removed, revert to original |
| 780 | * inode format making all literal area available | 785 | * inode format making all literal area available |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 7ceabd0e2d9d..d1236d6f4045 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
| @@ -550,7 +550,7 @@ xfs_fs_goingdown( | |||
| 550 | struct vfs *vfsp = XFS_MTOVFS(mp); | 550 | struct vfs *vfsp = XFS_MTOVFS(mp); |
| 551 | struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev); | 551 | struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev); |
| 552 | 552 | ||
| 553 | if (sb) { | 553 | if (sb && !IS_ERR(sb)) { |
| 554 | xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); | 554 | xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); |
| 555 | thaw_bdev(sb->s_bdev, sb); | 555 | thaw_bdev(sb->s_bdev, sb); |
| 556 | } | 556 | } |
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index fcd6d63bb68b..3ce204a524b0 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h | |||
| @@ -69,7 +69,7 @@ typedef struct xfs_iomap { | |||
| 69 | xfs_buftarg_t *iomap_target; | 69 | xfs_buftarg_t *iomap_target; |
| 70 | xfs_off_t iomap_offset; /* offset of mapping, bytes */ | 70 | xfs_off_t iomap_offset; /* offset of mapping, bytes */ |
| 71 | xfs_off_t iomap_bsize; /* size of mapping, bytes */ | 71 | xfs_off_t iomap_bsize; /* size of mapping, bytes */ |
| 72 | size_t iomap_delta; /* offset into mapping, bytes */ | 72 | xfs_off_t iomap_delta; /* offset into mapping, bytes */ |
| 73 | iomap_flags_t iomap_flags; | 73 | iomap_flags_t iomap_flags; |
| 74 | } xfs_iomap_t; | 74 | } xfs_iomap_t; |
| 75 | 75 | ||
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 8f285149681f..4518b188ade6 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
| @@ -494,10 +494,8 @@ typedef struct log { | |||
| 494 | 494 | ||
| 495 | #define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR) | 495 | #define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR) |
| 496 | 496 | ||
| 497 | #define XLOG_GRANT_SUB_SPACE(log,bytes,type) \ | 497 | #define XLOG_GRANT_SUB_SPACE(log,bytes,type) \ |
| 498 | xlog_grant_sub_space(log,bytes,type) | 498 | { \ |
| 499 | static inline void xlog_grant_sub_space(struct log *log, int bytes, int type) | ||
| 500 | { | ||
| 501 | if (type == 'w') { \ | 499 | if (type == 'w') { \ |
| 502 | (log)->l_grant_write_bytes -= (bytes); \ | 500 | (log)->l_grant_write_bytes -= (bytes); \ |
| 503 | if ((log)->l_grant_write_bytes < 0) { \ | 501 | if ((log)->l_grant_write_bytes < 0) { \ |
| @@ -511,13 +509,9 @@ static inline void xlog_grant_sub_space(struct log *log, int bytes, int type) | |||
| 511 | (log)->l_grant_reserve_cycle--; \ | 509 | (log)->l_grant_reserve_cycle--; \ |
| 512 | } \ | 510 | } \ |
| 513 | } \ | 511 | } \ |
| 514 | } | 512 | } |
| 515 | 513 | #define XLOG_GRANT_ADD_SPACE(log,bytes,type) \ | |
| 516 | #define XLOG_GRANT_ADD_SPACE(log,bytes,type) \ | 514 | { \ |
| 517 | xlog_grant_add_space(log,bytes,type) | ||
| 518 | static inline void | ||
| 519 | xlog_grant_add_space(struct log *log, int bytes, int type) | ||
| 520 | { | ||
| 521 | if (type == 'w') { \ | 515 | if (type == 'w') { \ |
| 522 | (log)->l_grant_write_bytes += (bytes); \ | 516 | (log)->l_grant_write_bytes += (bytes); \ |
| 523 | if ((log)->l_grant_write_bytes > (log)->l_logsize) { \ | 517 | if ((log)->l_grant_write_bytes > (log)->l_logsize) { \ |
| @@ -531,12 +525,9 @@ xlog_grant_add_space(struct log *log, int bytes, int type) | |||
| 531 | (log)->l_grant_reserve_cycle++; \ | 525 | (log)->l_grant_reserve_cycle++; \ |
| 532 | } \ | 526 | } \ |
| 533 | } \ | 527 | } \ |
| 534 | } | 528 | } |
| 535 | 529 | #define XLOG_INS_TICKETQ(q, tic) \ | |
| 536 | #define XLOG_INS_TICKETQ(q, tic) xlog_ins_ticketq(q, tic) | 530 | { \ |
| 537 | static inline void | ||
| 538 | xlog_ins_ticketq(struct xlog_ticket *q, struct xlog_ticket *tic) | ||
| 539 | { \ | ||
| 540 | if (q) { \ | 531 | if (q) { \ |
| 541 | (tic)->t_next = (q); \ | 532 | (tic)->t_next = (q); \ |
| 542 | (tic)->t_prev = (q)->t_prev; \ | 533 | (tic)->t_prev = (q)->t_prev; \ |
| @@ -547,12 +538,9 @@ xlog_ins_ticketq(struct xlog_ticket *q, struct xlog_ticket *tic) | |||
| 547 | (q) = (tic); \ | 538 | (q) = (tic); \ |
| 548 | } \ | 539 | } \ |
| 549 | (tic)->t_flags |= XLOG_TIC_IN_Q; \ | 540 | (tic)->t_flags |= XLOG_TIC_IN_Q; \ |
| 550 | } | 541 | } |
| 551 | 542 | #define XLOG_DEL_TICKETQ(q, tic) \ | |
| 552 | #define XLOG_DEL_TICKETQ(q, tic) xlog_del_ticketq(q, tic) | 543 | { \ |
| 553 | static inline void | ||
| 554 | xlog_del_ticketq(struct xlog_ticket *q, struct xlog_ticket *tic) | ||
| 555 | { \ | ||
| 556 | if ((tic) == (tic)->t_next) { \ | 544 | if ((tic) == (tic)->t_next) { \ |
| 557 | (q) = NULL; \ | 545 | (q) = NULL; \ |
| 558 | } else { \ | 546 | } else { \ |
| @@ -562,7 +550,7 @@ xlog_del_ticketq(struct xlog_ticket *q, struct xlog_ticket *tic) | |||
| 562 | } \ | 550 | } \ |
| 563 | (tic)->t_next = (tic)->t_prev = NULL; \ | 551 | (tic)->t_next = (tic)->t_prev = NULL; \ |
| 564 | (tic)->t_flags &= ~XLOG_TIC_IN_Q; \ | 552 | (tic)->t_flags &= ~XLOG_TIC_IN_Q; \ |
| 565 | } | 553 | } |
| 566 | 554 | ||
| 567 | /* common routines */ | 555 | /* common routines */ |
| 568 | extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); | 556 | extern xfs_lsn_t xlog_assign_tail_lsn(struct xfs_mount *mp); |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 7c1f74531463..e03fa2a3d5ed 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
| @@ -3958,8 +3958,9 @@ xfs_finish_reclaim_all(xfs_mount_t *mp, int noblock) | |||
| 3958 | } | 3958 | } |
| 3959 | } | 3959 | } |
| 3960 | XFS_MOUNT_IUNLOCK(mp); | 3960 | XFS_MOUNT_IUNLOCK(mp); |
| 3961 | xfs_finish_reclaim(ip, noblock, | 3961 | if (xfs_finish_reclaim(ip, noblock, |
| 3962 | XFS_IFLUSH_DELWRI_ELSE_ASYNC); | 3962 | XFS_IFLUSH_DELWRI_ELSE_ASYNC)) |
| 3963 | delay(1); | ||
| 3963 | purged = 1; | 3964 | purged = 1; |
| 3964 | break; | 3965 | break; |
| 3965 | } | 3966 | } |
