aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/direct.c2
-rw-r--r--fs/nfs/pnfs.c13
-rw-r--r--fs/nfs/super.c2
-rw-r--r--fs/nfs/write.c83
4 files changed, 56 insertions, 44 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 8c10b0562e75..621c517b325c 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -86,10 +86,10 @@ struct nfs_direct_req {
86 struct nfs_direct_mirror mirrors[NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX]; 86 struct nfs_direct_mirror mirrors[NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX];
87 int mirror_count; 87 int mirror_count;
88 88
89 loff_t io_start; /* Start offset for I/O */
89 ssize_t count, /* bytes actually processed */ 90 ssize_t count, /* bytes actually processed */
90 max_count, /* max expected count */ 91 max_count, /* max expected count */
91 bytes_left, /* bytes left to be sent */ 92 bytes_left, /* bytes left to be sent */
92 io_start, /* start of IO */
93 error; /* any reported error */ 93 error; /* any reported error */
94 struct completion completion; /* wait for i/o completion */ 94 struct completion completion; /* wait for i/o completion */
95 95
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index c13e826614b5..ee723aa153a3 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -292,8 +292,11 @@ pnfs_detach_layout_hdr(struct pnfs_layout_hdr *lo)
292void 292void
293pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo) 293pnfs_put_layout_hdr(struct pnfs_layout_hdr *lo)
294{ 294{
295 struct inode *inode = lo->plh_inode; 295 struct inode *inode;
296 296
297 if (!lo)
298 return;
299 inode = lo->plh_inode;
297 pnfs_layoutreturn_before_put_layout_hdr(lo); 300 pnfs_layoutreturn_before_put_layout_hdr(lo);
298 301
299 if (refcount_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) { 302 if (refcount_dec_and_lock(&lo->plh_refcount, &inode->i_lock)) {
@@ -1241,10 +1244,12 @@ retry:
1241 spin_lock(&ino->i_lock); 1244 spin_lock(&ino->i_lock);
1242 lo = nfsi->layout; 1245 lo = nfsi->layout;
1243 if (!lo || !pnfs_layout_is_valid(lo) || 1246 if (!lo || !pnfs_layout_is_valid(lo) ||
1244 test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) 1247 test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags)) {
1248 lo = NULL;
1245 goto out_noroc; 1249 goto out_noroc;
1250 }
1251 pnfs_get_layout_hdr(lo);
1246 if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) { 1252 if (test_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) {
1247 pnfs_get_layout_hdr(lo);
1248 spin_unlock(&ino->i_lock); 1253 spin_unlock(&ino->i_lock);
1249 wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN, 1254 wait_on_bit(&lo->plh_flags, NFS_LAYOUT_RETURN,
1250 TASK_UNINTERRUPTIBLE); 1255 TASK_UNINTERRUPTIBLE);
@@ -1312,10 +1317,12 @@ out_noroc:
1312 struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld; 1317 struct pnfs_layoutdriver_type *ld = NFS_SERVER(ino)->pnfs_curr_ld;
1313 if (ld->prepare_layoutreturn) 1318 if (ld->prepare_layoutreturn)
1314 ld->prepare_layoutreturn(args); 1319 ld->prepare_layoutreturn(args);
1320 pnfs_put_layout_hdr(lo);
1315 return true; 1321 return true;
1316 } 1322 }
1317 if (layoutreturn) 1323 if (layoutreturn)
1318 pnfs_send_layoutreturn(lo, &stateid, iomode, true); 1324 pnfs_send_layoutreturn(lo, &stateid, iomode, true);
1325 pnfs_put_layout_hdr(lo);
1319 return false; 1326 return false;
1320} 1327}
1321 1328
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 29bacdc56f6a..5e470e233c83 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2631,6 +2631,8 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server,
2631 /* initial superblock/root creation */ 2631 /* initial superblock/root creation */
2632 mount_info->fill_super(s, mount_info); 2632 mount_info->fill_super(s, mount_info);
2633 nfs_get_cache_cookie(s, mount_info->parsed, mount_info->cloned); 2633 nfs_get_cache_cookie(s, mount_info->parsed, mount_info->cloned);
2634 if (!(server->flags & NFS_MOUNT_UNSHARED))
2635 s->s_iflags |= SB_I_MULTIROOT;
2634 } 2636 }
2635 2637
2636 mntroot = nfs_get_root(s, mount_info->mntfh, dev_name); 2638 mntroot = nfs_get_root(s, mount_info->mntfh, dev_name);
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 7428a669d7a7..e7d8ceae8f26 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1876,40 +1876,43 @@ int nfs_generic_commit_list(struct inode *inode, struct list_head *head,
1876 return status; 1876 return status;
1877} 1877}
1878 1878
1879int nfs_commit_inode(struct inode *inode, int how) 1879static int __nfs_commit_inode(struct inode *inode, int how,
1880 struct writeback_control *wbc)
1880{ 1881{
1881 LIST_HEAD(head); 1882 LIST_HEAD(head);
1882 struct nfs_commit_info cinfo; 1883 struct nfs_commit_info cinfo;
1883 int may_wait = how & FLUSH_SYNC; 1884 int may_wait = how & FLUSH_SYNC;
1884 int error = 0; 1885 int ret, nscan;
1885 int res;
1886 1886
1887 nfs_init_cinfo_from_inode(&cinfo, inode); 1887 nfs_init_cinfo_from_inode(&cinfo, inode);
1888 nfs_commit_begin(cinfo.mds); 1888 nfs_commit_begin(cinfo.mds);
1889 res = nfs_scan_commit(inode, &head, &cinfo); 1889 for (;;) {
1890 if (res) 1890 ret = nscan = nfs_scan_commit(inode, &head, &cinfo);
1891 error = nfs_generic_commit_list(inode, &head, how, &cinfo); 1891 if (ret <= 0)
1892 break;
1893 ret = nfs_generic_commit_list(inode, &head, how, &cinfo);
1894 if (ret < 0)
1895 break;
1896 ret = 0;
1897 if (wbc && wbc->sync_mode == WB_SYNC_NONE) {
1898 if (nscan < wbc->nr_to_write)
1899 wbc->nr_to_write -= nscan;
1900 else
1901 wbc->nr_to_write = 0;
1902 }
1903 if (nscan < INT_MAX)
1904 break;
1905 cond_resched();
1906 }
1892 nfs_commit_end(cinfo.mds); 1907 nfs_commit_end(cinfo.mds);
1893 if (res == 0) 1908 if (ret || !may_wait)
1894 return res; 1909 return ret;
1895 if (error < 0) 1910 return wait_on_commit(cinfo.mds);
1896 goto out_error; 1911}
1897 if (!may_wait) 1912
1898 goto out_mark_dirty; 1913int nfs_commit_inode(struct inode *inode, int how)
1899 error = wait_on_commit(cinfo.mds); 1914{
1900 if (error < 0) 1915 return __nfs_commit_inode(inode, how, NULL);
1901 return error;
1902 return res;
1903out_error:
1904 res = error;
1905 /* Note: If we exit without ensuring that the commit is complete,
1906 * we must mark the inode as dirty. Otherwise, future calls to
1907 * sync_inode() with the WB_SYNC_ALL flag set will fail to ensure
1908 * that the data is on the disk.
1909 */
1910out_mark_dirty:
1911 __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
1912 return res;
1913} 1916}
1914EXPORT_SYMBOL_GPL(nfs_commit_inode); 1917EXPORT_SYMBOL_GPL(nfs_commit_inode);
1915 1918
@@ -1919,11 +1922,11 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
1919 int flags = FLUSH_SYNC; 1922 int flags = FLUSH_SYNC;
1920 int ret = 0; 1923 int ret = 0;
1921 1924
1922 /* no commits means nothing needs to be done */
1923 if (!atomic_long_read(&nfsi->commit_info.ncommit))
1924 return ret;
1925
1926 if (wbc->sync_mode == WB_SYNC_NONE) { 1925 if (wbc->sync_mode == WB_SYNC_NONE) {
1926 /* no commits means nothing needs to be done */
1927 if (!atomic_long_read(&nfsi->commit_info.ncommit))
1928 goto check_requests_outstanding;
1929
1927 /* Don't commit yet if this is a non-blocking flush and there 1930 /* Don't commit yet if this is a non-blocking flush and there
1928 * are a lot of outstanding writes for this mapping. 1931 * are a lot of outstanding writes for this mapping.
1929 */ 1932 */
@@ -1934,16 +1937,16 @@ int nfs_write_inode(struct inode *inode, struct writeback_control *wbc)
1934 flags = 0; 1937 flags = 0;
1935 } 1938 }
1936 1939
1937 ret = nfs_commit_inode(inode, flags); 1940 ret = __nfs_commit_inode(inode, flags, wbc);
1938 if (ret >= 0) { 1941 if (!ret) {
1939 if (wbc->sync_mode == WB_SYNC_NONE) { 1942 if (flags & FLUSH_SYNC)
1940 if (ret < wbc->nr_to_write) 1943 return 0;
1941 wbc->nr_to_write -= ret; 1944 } else if (atomic_long_read(&nfsi->commit_info.ncommit))
1942 else 1945 goto out_mark_dirty;
1943 wbc->nr_to_write = 0; 1946
1944 } 1947check_requests_outstanding:
1945 return 0; 1948 if (!atomic_read(&nfsi->commit_info.rpcs_out))
1946 } 1949 return ret;
1947out_mark_dirty: 1950out_mark_dirty:
1948 __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 1951 __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
1949 return ret; 1952 return ret;