diff options
-rw-r--r-- | fs/cifs/cifsfs.h | 1 | ||||
-rw-r--r-- | fs/cifs/cifsglob.h | 1 | ||||
-rw-r--r-- | fs/cifs/file.c | 12 | ||||
-rw-r--r-- | fs/cifs/inode.c | 50 |
4 files changed, 49 insertions, 15 deletions
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 63d51274dfbf..1bbe97c2a632 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -76,6 +76,7 @@ extern int cifs_revalidate_file(struct file *filp); | |||
76 | extern int cifs_revalidate_dentry(struct dentry *); | 76 | extern int cifs_revalidate_dentry(struct dentry *); |
77 | extern int cifs_invalidate_mapping(struct inode *inode); | 77 | extern int cifs_invalidate_mapping(struct inode *inode); |
78 | extern int cifs_revalidate_mapping(struct inode *inode); | 78 | extern int cifs_revalidate_mapping(struct inode *inode); |
79 | extern int cifs_zap_mapping(struct inode *inode); | ||
79 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 80 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
80 | extern int cifs_setattr(struct dentry *, struct iattr *); | 81 | extern int cifs_setattr(struct dentry *, struct iattr *); |
81 | 82 | ||
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 69da55b750e7..630e0f4b2c66 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -1118,6 +1118,7 @@ struct cifsInodeInfo { | |||
1118 | #define CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 (2) /* Downgrade oplock to L2 */ | 1118 | #define CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 (2) /* Downgrade oplock to L2 */ |
1119 | #define CIFS_INO_DELETE_PENDING (3) /* delete pending on server */ | 1119 | #define CIFS_INO_DELETE_PENDING (3) /* delete pending on server */ |
1120 | #define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */ | 1120 | #define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */ |
1121 | #define CIFS_INO_LOCK (5) /* lock bit for synchronization */ | ||
1121 | unsigned long flags; | 1122 | unsigned long flags; |
1122 | spinlock_t writers_lock; | 1123 | spinlock_t writers_lock; |
1123 | unsigned int writers; /* Number of writers on this inode */ | 1124 | unsigned int writers; /* Number of writers on this inode */ |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index c8a570e87900..208f56eca4bf 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -335,7 +335,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, | |||
335 | spin_unlock(&cifs_file_list_lock); | 335 | spin_unlock(&cifs_file_list_lock); |
336 | 336 | ||
337 | if (fid->purge_cache) | 337 | if (fid->purge_cache) |
338 | cifs_invalidate_mapping(inode); | 338 | cifs_zap_mapping(inode); |
339 | 339 | ||
340 | file->private_data = cfile; | 340 | file->private_data = cfile; |
341 | return cfile; | 341 | return cfile; |
@@ -1529,7 +1529,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, | |||
1529 | */ | 1529 | */ |
1530 | if (!CIFS_CACHE_WRITE(CIFS_I(inode)) && | 1530 | if (!CIFS_CACHE_WRITE(CIFS_I(inode)) && |
1531 | CIFS_CACHE_READ(CIFS_I(inode))) { | 1531 | CIFS_CACHE_READ(CIFS_I(inode))) { |
1532 | cifs_invalidate_mapping(inode); | 1532 | cifs_zap_mapping(inode); |
1533 | cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n", | 1533 | cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n", |
1534 | inode); | 1534 | inode); |
1535 | CIFS_I(inode)->oplock = 0; | 1535 | CIFS_I(inode)->oplock = 0; |
@@ -2218,7 +2218,7 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, | |||
2218 | file->f_path.dentry->d_name.name, datasync); | 2218 | file->f_path.dentry->d_name.name, datasync); |
2219 | 2219 | ||
2220 | if (!CIFS_CACHE_READ(CIFS_I(inode))) { | 2220 | if (!CIFS_CACHE_READ(CIFS_I(inode))) { |
2221 | rc = cifs_invalidate_mapping(inode); | 2221 | rc = cifs_zap_mapping(inode); |
2222 | if (rc) { | 2222 | if (rc) { |
2223 | cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc); | 2223 | cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc); |
2224 | rc = 0; /* don't care about it in fsync */ | 2224 | rc = 0; /* don't care about it in fsync */ |
@@ -2649,7 +2649,7 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, | |||
2649 | * request comes - break it on the client to prevent reading | 2649 | * request comes - break it on the client to prevent reading |
2650 | * an old data. | 2650 | * an old data. |
2651 | */ | 2651 | */ |
2652 | cifs_invalidate_mapping(inode); | 2652 | cifs_zap_mapping(inode); |
2653 | cifs_dbg(FYI, "Set no oplock for inode=%p after a write operation\n", | 2653 | cifs_dbg(FYI, "Set no oplock for inode=%p after a write operation\n", |
2654 | inode); | 2654 | inode); |
2655 | cinode->oplock = 0; | 2655 | cinode->oplock = 0; |
@@ -3112,7 +3112,7 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) | |||
3112 | xid = get_xid(); | 3112 | xid = get_xid(); |
3113 | 3113 | ||
3114 | if (!CIFS_CACHE_READ(CIFS_I(inode))) { | 3114 | if (!CIFS_CACHE_READ(CIFS_I(inode))) { |
3115 | rc = cifs_invalidate_mapping(inode); | 3115 | rc = cifs_zap_mapping(inode); |
3116 | if (rc) | 3116 | if (rc) |
3117 | return rc; | 3117 | return rc; |
3118 | } | 3118 | } |
@@ -3670,7 +3670,7 @@ void cifs_oplock_break(struct work_struct *work) | |||
3670 | if (!CIFS_CACHE_READ(cinode)) { | 3670 | if (!CIFS_CACHE_READ(cinode)) { |
3671 | rc = filemap_fdatawait(inode->i_mapping); | 3671 | rc = filemap_fdatawait(inode->i_mapping); |
3672 | mapping_set_error(inode->i_mapping, rc); | 3672 | mapping_set_error(inode->i_mapping, rc); |
3673 | cifs_invalidate_mapping(inode); | 3673 | cifs_zap_mapping(inode); |
3674 | } | 3674 | } |
3675 | cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc); | 3675 | cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc); |
3676 | } | 3676 | } |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ff420b275777..9ff8df8b4d84 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/stat.h> | 22 | #include <linux/stat.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/pagemap.h> | 24 | #include <linux/pagemap.h> |
25 | #include <linux/freezer.h> | ||
25 | #include <asm/div64.h> | 26 | #include <asm/div64.h> |
26 | #include "cifsfs.h" | 27 | #include "cifsfs.h" |
27 | #include "cifspdu.h" | 28 | #include "cifspdu.h" |
@@ -1762,29 +1763,60 @@ int | |||
1762 | cifs_invalidate_mapping(struct inode *inode) | 1763 | cifs_invalidate_mapping(struct inode *inode) |
1763 | { | 1764 | { |
1764 | int rc = 0; | 1765 | int rc = 0; |
1765 | struct cifsInodeInfo *cifs_i = CIFS_I(inode); | ||
1766 | |||
1767 | clear_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags); | ||
1768 | 1766 | ||
1769 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { | 1767 | if (inode->i_mapping && inode->i_mapping->nrpages != 0) { |
1770 | rc = invalidate_inode_pages2(inode->i_mapping); | 1768 | rc = invalidate_inode_pages2(inode->i_mapping); |
1771 | if (rc) { | 1769 | if (rc) |
1772 | cifs_dbg(VFS, "%s: could not invalidate inode %p\n", | 1770 | cifs_dbg(VFS, "%s: could not invalidate inode %p\n", |
1773 | __func__, inode); | 1771 | __func__, inode); |
1774 | set_bit(CIFS_INO_INVALID_MAPPING, &cifs_i->flags); | ||
1775 | } | ||
1776 | } | 1772 | } |
1777 | 1773 | ||
1778 | cifs_fscache_reset_inode_cookie(inode); | 1774 | cifs_fscache_reset_inode_cookie(inode); |
1779 | return rc; | 1775 | return rc; |
1780 | } | 1776 | } |
1781 | 1777 | ||
1778 | /** | ||
1779 | * cifs_wait_bit_killable - helper for functions that are sleeping on bit locks | ||
1780 | * @word: long word containing the bit lock | ||
1781 | */ | ||
1782 | static int | ||
1783 | cifs_wait_bit_killable(void *word) | ||
1784 | { | ||
1785 | if (fatal_signal_pending(current)) | ||
1786 | return -ERESTARTSYS; | ||
1787 | freezable_schedule_unsafe(); | ||
1788 | return 0; | ||
1789 | } | ||
1790 | |||
1782 | int | 1791 | int |
1783 | cifs_revalidate_mapping(struct inode *inode) | 1792 | cifs_revalidate_mapping(struct inode *inode) |
1784 | { | 1793 | { |
1785 | if (test_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags)) | 1794 | int rc; |
1786 | return cifs_invalidate_mapping(inode); | 1795 | unsigned long *flags = &CIFS_I(inode)->flags; |
1787 | return 0; | 1796 | |
1797 | rc = wait_on_bit_lock(flags, CIFS_INO_LOCK, cifs_wait_bit_killable, | ||
1798 | TASK_KILLABLE); | ||
1799 | if (rc) | ||
1800 | return rc; | ||
1801 | |||
1802 | if (test_and_clear_bit(CIFS_INO_INVALID_MAPPING, flags)) { | ||
1803 | rc = cifs_invalidate_mapping(inode); | ||
1804 | if (rc) | ||
1805 | set_bit(CIFS_INO_INVALID_MAPPING, flags); | ||
1806 | } | ||
1807 | |||
1808 | clear_bit_unlock(CIFS_INO_LOCK, flags); | ||
1809 | smp_mb__after_clear_bit(); | ||
1810 | wake_up_bit(flags, CIFS_INO_LOCK); | ||
1811 | |||
1812 | return rc; | ||
1813 | } | ||
1814 | |||
1815 | int | ||
1816 | cifs_zap_mapping(struct inode *inode) | ||
1817 | { | ||
1818 | set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(inode)->flags); | ||
1819 | return cifs_revalidate_mapping(inode); | ||
1788 | } | 1820 | } |
1789 | 1821 | ||
1790 | int cifs_revalidate_file_attr(struct file *filp) | 1822 | int cifs_revalidate_file_attr(struct file *filp) |