diff options
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/blocklayout/blocklayout.c | 43 | ||||
-rw-r--r-- | fs/nfs/dir.c | 36 | ||||
-rw-r--r-- | fs/nfs/direct.c | 279 | ||||
-rw-r--r-- | fs/nfs/file.c | 6 | ||||
-rw-r--r-- | fs/nfs/inode.c | 103 | ||||
-rw-r--r-- | fs/nfs/nfs3acl.c | 295 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 76 | ||||
-rw-r--r-- | fs/nfs/nfs3super.c | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4_fs.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4client.c | 22 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 24 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 82 | ||||
-rw-r--r-- | fs/nfs/nfs4session.c | 25 | ||||
-rw-r--r-- | fs/nfs/nfs4session.h | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4super.c | 14 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 49 | ||||
-rw-r--r-- | fs/nfs/nfstrace.h | 1 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 67 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 16 | ||||
-rw-r--r-- | fs/nfs/read.c | 12 | ||||
-rw-r--r-- | fs/nfs/write.c | 26 |
23 files changed, 594 insertions, 594 deletions
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index e242bbf72972..56ff823ca82e 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c | |||
@@ -134,8 +134,8 @@ bl_submit_bio(int rw, struct bio *bio) | |||
134 | if (bio) { | 134 | if (bio) { |
135 | get_parallel(bio->bi_private); | 135 | get_parallel(bio->bi_private); |
136 | dprintk("%s submitting %s bio %u@%llu\n", __func__, | 136 | dprintk("%s submitting %s bio %u@%llu\n", __func__, |
137 | rw == READ ? "read" : "write", | 137 | rw == READ ? "read" : "write", bio->bi_iter.bi_size, |
138 | bio->bi_size, (unsigned long long)bio->bi_sector); | 138 | (unsigned long long)bio->bi_iter.bi_sector); |
139 | submit_bio(rw, bio); | 139 | submit_bio(rw, bio); |
140 | } | 140 | } |
141 | return NULL; | 141 | return NULL; |
@@ -156,7 +156,8 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect, | |||
156 | } | 156 | } |
157 | 157 | ||
158 | if (bio) { | 158 | if (bio) { |
159 | bio->bi_sector = isect - be->be_f_offset + be->be_v_offset; | 159 | bio->bi_iter.bi_sector = isect - be->be_f_offset + |
160 | be->be_v_offset; | ||
160 | bio->bi_bdev = be->be_mdev; | 161 | bio->bi_bdev = be->be_mdev; |
161 | bio->bi_end_io = end_io; | 162 | bio->bi_end_io = end_io; |
162 | bio->bi_private = par; | 163 | bio->bi_private = par; |
@@ -201,18 +202,14 @@ static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw, | |||
201 | static void bl_end_io_read(struct bio *bio, int err) | 202 | static void bl_end_io_read(struct bio *bio, int err) |
202 | { | 203 | { |
203 | struct parallel_io *par = bio->bi_private; | 204 | struct parallel_io *par = bio->bi_private; |
204 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 205 | struct bio_vec *bvec; |
205 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 206 | int i; |
206 | 207 | ||
207 | do { | 208 | if (!err) |
208 | struct page *page = bvec->bv_page; | 209 | bio_for_each_segment_all(bvec, bio, i) |
210 | SetPageUptodate(bvec->bv_page); | ||
209 | 211 | ||
210 | if (--bvec >= bio->bi_io_vec) | 212 | if (err) { |
211 | prefetchw(&bvec->bv_page->flags); | ||
212 | if (uptodate) | ||
213 | SetPageUptodate(page); | ||
214 | } while (bvec >= bio->bi_io_vec); | ||
215 | if (!uptodate) { | ||
216 | struct nfs_read_data *rdata = par->data; | 213 | struct nfs_read_data *rdata = par->data; |
217 | struct nfs_pgio_header *header = rdata->header; | 214 | struct nfs_pgio_header *header = rdata->header; |
218 | 215 | ||
@@ -383,20 +380,16 @@ static void mark_extents_written(struct pnfs_block_layout *bl, | |||
383 | static void bl_end_io_write_zero(struct bio *bio, int err) | 380 | static void bl_end_io_write_zero(struct bio *bio, int err) |
384 | { | 381 | { |
385 | struct parallel_io *par = bio->bi_private; | 382 | struct parallel_io *par = bio->bi_private; |
386 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 383 | struct bio_vec *bvec; |
387 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 384 | int i; |
388 | |||
389 | do { | ||
390 | struct page *page = bvec->bv_page; | ||
391 | 385 | ||
392 | if (--bvec >= bio->bi_io_vec) | 386 | bio_for_each_segment_all(bvec, bio, i) { |
393 | prefetchw(&bvec->bv_page->flags); | ||
394 | /* This is the zeroing page we added */ | 387 | /* This is the zeroing page we added */ |
395 | end_page_writeback(page); | 388 | end_page_writeback(bvec->bv_page); |
396 | page_cache_release(page); | 389 | page_cache_release(bvec->bv_page); |
397 | } while (bvec >= bio->bi_io_vec); | 390 | } |
398 | 391 | ||
399 | if (unlikely(!uptodate)) { | 392 | if (unlikely(err)) { |
400 | struct nfs_write_data *data = par->data; | 393 | struct nfs_write_data *data = par->data; |
401 | struct nfs_pgio_header *header = data->header; | 394 | struct nfs_pgio_header *header = data->header; |
402 | 395 | ||
@@ -519,7 +512,7 @@ bl_do_readpage_sync(struct page *page, struct pnfs_block_extent *be, | |||
519 | isect = (page->index << PAGE_CACHE_SECTOR_SHIFT) + | 512 | isect = (page->index << PAGE_CACHE_SECTOR_SHIFT) + |
520 | (offset / SECTOR_SIZE); | 513 | (offset / SECTOR_SIZE); |
521 | 514 | ||
522 | bio->bi_sector = isect - be->be_f_offset + be->be_v_offset; | 515 | bio->bi_iter.bi_sector = isect - be->be_f_offset + be->be_v_offset; |
523 | bio->bi_bdev = be->be_mdev; | 516 | bio->bi_bdev = be->be_mdev; |
524 | bio->bi_end_io = bl_read_single_end_io; | 517 | bio->bi_end_io = bl_read_single_end_io; |
525 | 518 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 812154aff981..4a48fe4b84b6 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -274,6 +274,15 @@ out_eof: | |||
274 | return -EBADCOOKIE; | 274 | return -EBADCOOKIE; |
275 | } | 275 | } |
276 | 276 | ||
277 | static bool | ||
278 | nfs_readdir_inode_mapping_valid(struct nfs_inode *nfsi) | ||
279 | { | ||
280 | if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) | ||
281 | return false; | ||
282 | smp_rmb(); | ||
283 | return !test_bit(NFS_INO_INVALIDATING, &nfsi->flags); | ||
284 | } | ||
285 | |||
277 | static | 286 | static |
278 | int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) | 287 | int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc) |
279 | { | 288 | { |
@@ -287,8 +296,8 @@ int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_des | |||
287 | struct nfs_open_dir_context *ctx = desc->file->private_data; | 296 | struct nfs_open_dir_context *ctx = desc->file->private_data; |
288 | 297 | ||
289 | new_pos = desc->current_index + i; | 298 | new_pos = desc->current_index + i; |
290 | if (ctx->attr_gencount != nfsi->attr_gencount | 299 | if (ctx->attr_gencount != nfsi->attr_gencount || |
291 | || (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA))) { | 300 | !nfs_readdir_inode_mapping_valid(nfsi)) { |
292 | ctx->duped = 0; | 301 | ctx->duped = 0; |
293 | ctx->attr_gencount = nfsi->attr_gencount; | 302 | ctx->attr_gencount = nfsi->attr_gencount; |
294 | } else if (new_pos < desc->ctx->pos) { | 303 | } else if (new_pos < desc->ctx->pos) { |
@@ -1404,7 +1413,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, | |||
1404 | /* Expect a negative dentry */ | 1413 | /* Expect a negative dentry */ |
1405 | BUG_ON(dentry->d_inode); | 1414 | BUG_ON(dentry->d_inode); |
1406 | 1415 | ||
1407 | dfprintk(VFS, "NFS: atomic_open(%s/%ld), %pd\n", | 1416 | dfprintk(VFS, "NFS: atomic_open(%s/%lu), %pd\n", |
1408 | dir->i_sb->s_id, dir->i_ino, dentry); | 1417 | dir->i_sb->s_id, dir->i_ino, dentry); |
1409 | 1418 | ||
1410 | err = nfs_check_flags(open_flags); | 1419 | err = nfs_check_flags(open_flags); |
@@ -1594,7 +1603,7 @@ int nfs_create(struct inode *dir, struct dentry *dentry, | |||
1594 | int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT; | 1603 | int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT; |
1595 | int error; | 1604 | int error; |
1596 | 1605 | ||
1597 | dfprintk(VFS, "NFS: create(%s/%ld), %pd\n", | 1606 | dfprintk(VFS, "NFS: create(%s/%lu), %pd\n", |
1598 | dir->i_sb->s_id, dir->i_ino, dentry); | 1607 | dir->i_sb->s_id, dir->i_ino, dentry); |
1599 | 1608 | ||
1600 | attr.ia_mode = mode; | 1609 | attr.ia_mode = mode; |
@@ -1621,7 +1630,7 @@ nfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) | |||
1621 | struct iattr attr; | 1630 | struct iattr attr; |
1622 | int status; | 1631 | int status; |
1623 | 1632 | ||
1624 | dfprintk(VFS, "NFS: mknod(%s/%ld), %pd\n", | 1633 | dfprintk(VFS, "NFS: mknod(%s/%lu), %pd\n", |
1625 | dir->i_sb->s_id, dir->i_ino, dentry); | 1634 | dir->i_sb->s_id, dir->i_ino, dentry); |
1626 | 1635 | ||
1627 | if (!new_valid_dev(rdev)) | 1636 | if (!new_valid_dev(rdev)) |
@@ -1650,7 +1659,7 @@ int nfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
1650 | struct iattr attr; | 1659 | struct iattr attr; |
1651 | int error; | 1660 | int error; |
1652 | 1661 | ||
1653 | dfprintk(VFS, "NFS: mkdir(%s/%ld), %pd\n", | 1662 | dfprintk(VFS, "NFS: mkdir(%s/%lu), %pd\n", |
1654 | dir->i_sb->s_id, dir->i_ino, dentry); | 1663 | dir->i_sb->s_id, dir->i_ino, dentry); |
1655 | 1664 | ||
1656 | attr.ia_valid = ATTR_MODE; | 1665 | attr.ia_valid = ATTR_MODE; |
@@ -1678,7 +1687,7 @@ int nfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
1678 | { | 1687 | { |
1679 | int error; | 1688 | int error; |
1680 | 1689 | ||
1681 | dfprintk(VFS, "NFS: rmdir(%s/%ld), %pd\n", | 1690 | dfprintk(VFS, "NFS: rmdir(%s/%lu), %pd\n", |
1682 | dir->i_sb->s_id, dir->i_ino, dentry); | 1691 | dir->i_sb->s_id, dir->i_ino, dentry); |
1683 | 1692 | ||
1684 | trace_nfs_rmdir_enter(dir, dentry); | 1693 | trace_nfs_rmdir_enter(dir, dentry); |
@@ -1747,7 +1756,7 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry) | |||
1747 | int error; | 1756 | int error; |
1748 | int need_rehash = 0; | 1757 | int need_rehash = 0; |
1749 | 1758 | ||
1750 | dfprintk(VFS, "NFS: unlink(%s/%ld, %pd)\n", dir->i_sb->s_id, | 1759 | dfprintk(VFS, "NFS: unlink(%s/%lu, %pd)\n", dir->i_sb->s_id, |
1751 | dir->i_ino, dentry); | 1760 | dir->i_ino, dentry); |
1752 | 1761 | ||
1753 | trace_nfs_unlink_enter(dir, dentry); | 1762 | trace_nfs_unlink_enter(dir, dentry); |
@@ -1798,7 +1807,7 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
1798 | unsigned int pathlen = strlen(symname); | 1807 | unsigned int pathlen = strlen(symname); |
1799 | int error; | 1808 | int error; |
1800 | 1809 | ||
1801 | dfprintk(VFS, "NFS: symlink(%s/%ld, %pd, %s)\n", dir->i_sb->s_id, | 1810 | dfprintk(VFS, "NFS: symlink(%s/%lu, %pd, %s)\n", dir->i_sb->s_id, |
1802 | dir->i_ino, dentry, symname); | 1811 | dir->i_ino, dentry, symname); |
1803 | 1812 | ||
1804 | if (pathlen > PAGE_SIZE) | 1813 | if (pathlen > PAGE_SIZE) |
@@ -1821,7 +1830,7 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
1821 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); | 1830 | error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr); |
1822 | trace_nfs_symlink_exit(dir, dentry, error); | 1831 | trace_nfs_symlink_exit(dir, dentry, error); |
1823 | if (error != 0) { | 1832 | if (error != 0) { |
1824 | dfprintk(VFS, "NFS: symlink(%s/%ld, %pd, %s) error %d\n", | 1833 | dfprintk(VFS, "NFS: symlink(%s/%lu, %pd, %s) error %d\n", |
1825 | dir->i_sb->s_id, dir->i_ino, | 1834 | dir->i_sb->s_id, dir->i_ino, |
1826 | dentry, symname, error); | 1835 | dentry, symname, error); |
1827 | d_drop(dentry); | 1836 | d_drop(dentry); |
@@ -1837,6 +1846,11 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
1837 | GFP_KERNEL)) { | 1846 | GFP_KERNEL)) { |
1838 | SetPageUptodate(page); | 1847 | SetPageUptodate(page); |
1839 | unlock_page(page); | 1848 | unlock_page(page); |
1849 | /* | ||
1850 | * add_to_page_cache_lru() grabs an extra page refcount. | ||
1851 | * Drop it here to avoid leaking this page later. | ||
1852 | */ | ||
1853 | page_cache_release(page); | ||
1840 | } else | 1854 | } else |
1841 | __free_page(page); | 1855 | __free_page(page); |
1842 | 1856 | ||
@@ -2304,7 +2318,7 @@ out: | |||
2304 | if (!res && (mask & MAY_EXEC) && !execute_ok(inode)) | 2318 | if (!res && (mask & MAY_EXEC) && !execute_ok(inode)) |
2305 | res = -EACCES; | 2319 | res = -EACCES; |
2306 | 2320 | ||
2307 | dfprintk(VFS, "NFS: permission(%s/%ld), mask=0x%x, res=%d\n", | 2321 | dfprintk(VFS, "NFS: permission(%s/%lu), mask=0x%x, res=%d\n", |
2308 | inode->i_sb->s_id, inode->i_ino, mask, res); | 2322 | inode->i_sb->s_id, inode->i_ino, mask, res); |
2309 | return res; | 2323 | return res; |
2310 | out_notsup: | 2324 | out_notsup: |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index d71d66c9e0a1..b8797ae6831f 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -222,14 +222,31 @@ out: | |||
222 | * Synchronous I/O uses a stack-allocated iocb. Thus we can't trust | 222 | * Synchronous I/O uses a stack-allocated iocb. Thus we can't trust |
223 | * the iocb is still valid here if this is a synchronous request. | 223 | * the iocb is still valid here if this is a synchronous request. |
224 | */ | 224 | */ |
225 | static void nfs_direct_complete(struct nfs_direct_req *dreq) | 225 | static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write) |
226 | { | 226 | { |
227 | struct inode *inode = dreq->inode; | ||
228 | |||
229 | if (dreq->iocb && write) { | ||
230 | loff_t pos = dreq->iocb->ki_pos + dreq->count; | ||
231 | |||
232 | spin_lock(&inode->i_lock); | ||
233 | if (i_size_read(inode) < pos) | ||
234 | i_size_write(inode, pos); | ||
235 | spin_unlock(&inode->i_lock); | ||
236 | } | ||
237 | |||
238 | if (write) | ||
239 | nfs_zap_mapping(inode, inode->i_mapping); | ||
240 | |||
241 | inode_dio_done(inode); | ||
242 | |||
227 | if (dreq->iocb) { | 243 | if (dreq->iocb) { |
228 | long res = (long) dreq->error; | 244 | long res = (long) dreq->error; |
229 | if (!res) | 245 | if (!res) |
230 | res = (long) dreq->count; | 246 | res = (long) dreq->count; |
231 | aio_complete(dreq->iocb, res, 0); | 247 | aio_complete(dreq->iocb, res, 0); |
232 | } | 248 | } |
249 | |||
233 | complete_all(&dreq->completion); | 250 | complete_all(&dreq->completion); |
234 | 251 | ||
235 | nfs_direct_req_release(dreq); | 252 | nfs_direct_req_release(dreq); |
@@ -237,9 +254,9 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq) | |||
237 | 254 | ||
238 | static void nfs_direct_readpage_release(struct nfs_page *req) | 255 | static void nfs_direct_readpage_release(struct nfs_page *req) |
239 | { | 256 | { |
240 | dprintk("NFS: direct read done (%s/%lld %d@%lld)\n", | 257 | dprintk("NFS: direct read done (%s/%llu %d@%lld)\n", |
241 | req->wb_context->dentry->d_inode->i_sb->s_id, | 258 | req->wb_context->dentry->d_inode->i_sb->s_id, |
242 | (long long)NFS_FILEID(req->wb_context->dentry->d_inode), | 259 | (unsigned long long)NFS_FILEID(req->wb_context->dentry->d_inode), |
243 | req->wb_bytes, | 260 | req->wb_bytes, |
244 | (long long)req_offset(req)); | 261 | (long long)req_offset(req)); |
245 | nfs_release_request(req); | 262 | nfs_release_request(req); |
@@ -272,7 +289,7 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr) | |||
272 | } | 289 | } |
273 | out_put: | 290 | out_put: |
274 | if (put_dreq(dreq)) | 291 | if (put_dreq(dreq)) |
275 | nfs_direct_complete(dreq); | 292 | nfs_direct_complete(dreq, false); |
276 | hdr->release(hdr); | 293 | hdr->release(hdr); |
277 | } | 294 | } |
278 | 295 | ||
@@ -402,6 +419,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
402 | loff_t pos, bool uio) | 419 | loff_t pos, bool uio) |
403 | { | 420 | { |
404 | struct nfs_pageio_descriptor desc; | 421 | struct nfs_pageio_descriptor desc; |
422 | struct inode *inode = dreq->inode; | ||
405 | ssize_t result = -EINVAL; | 423 | ssize_t result = -EINVAL; |
406 | size_t requested_bytes = 0; | 424 | size_t requested_bytes = 0; |
407 | unsigned long seg; | 425 | unsigned long seg; |
@@ -410,6 +428,7 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
410 | &nfs_direct_read_completion_ops); | 428 | &nfs_direct_read_completion_ops); |
411 | get_dreq(dreq); | 429 | get_dreq(dreq); |
412 | desc.pg_dreq = dreq; | 430 | desc.pg_dreq = dreq; |
431 | atomic_inc(&inode->i_dio_count); | ||
413 | 432 | ||
414 | for (seg = 0; seg < nr_segs; seg++) { | 433 | for (seg = 0; seg < nr_segs; seg++) { |
415 | const struct iovec *vec = &iov[seg]; | 434 | const struct iovec *vec = &iov[seg]; |
@@ -429,26 +448,69 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq, | |||
429 | * generic layer handle the completion. | 448 | * generic layer handle the completion. |
430 | */ | 449 | */ |
431 | if (requested_bytes == 0) { | 450 | if (requested_bytes == 0) { |
451 | inode_dio_done(inode); | ||
432 | nfs_direct_req_release(dreq); | 452 | nfs_direct_req_release(dreq); |
433 | return result < 0 ? result : -EIO; | 453 | return result < 0 ? result : -EIO; |
434 | } | 454 | } |
435 | 455 | ||
436 | if (put_dreq(dreq)) | 456 | if (put_dreq(dreq)) |
437 | nfs_direct_complete(dreq); | 457 | nfs_direct_complete(dreq, false); |
438 | return 0; | 458 | return 0; |
439 | } | 459 | } |
440 | 460 | ||
441 | static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | 461 | /** |
442 | unsigned long nr_segs, loff_t pos, bool uio) | 462 | * nfs_file_direct_read - file direct read operation for NFS files |
463 | * @iocb: target I/O control block | ||
464 | * @iov: vector of user buffers into which to read data | ||
465 | * @nr_segs: size of iov vector | ||
466 | * @pos: byte offset in file where reading starts | ||
467 | * | ||
468 | * We use this function for direct reads instead of calling | ||
469 | * generic_file_aio_read() in order to avoid gfar's check to see if | ||
470 | * the request starts before the end of the file. For that check | ||
471 | * to work, we must generate a GETATTR before each direct read, and | ||
472 | * even then there is a window between the GETATTR and the subsequent | ||
473 | * READ where the file size could change. Our preference is simply | ||
474 | * to do all reads the application wants, and the server will take | ||
475 | * care of managing the end of file boundary. | ||
476 | * | ||
477 | * This function also eliminates unnecessarily updating the file's | ||
478 | * atime locally, as the NFS server sets the file's atime, and this | ||
479 | * client must read the updated atime from the server back into its | ||
480 | * cache. | ||
481 | */ | ||
482 | ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | ||
483 | unsigned long nr_segs, loff_t pos, bool uio) | ||
443 | { | 484 | { |
444 | ssize_t result = -ENOMEM; | 485 | struct file *file = iocb->ki_filp; |
445 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 486 | struct address_space *mapping = file->f_mapping; |
487 | struct inode *inode = mapping->host; | ||
446 | struct nfs_direct_req *dreq; | 488 | struct nfs_direct_req *dreq; |
447 | struct nfs_lock_context *l_ctx; | 489 | struct nfs_lock_context *l_ctx; |
490 | ssize_t result = -EINVAL; | ||
491 | size_t count; | ||
448 | 492 | ||
493 | count = iov_length(iov, nr_segs); | ||
494 | nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); | ||
495 | |||
496 | dfprintk(FILE, "NFS: direct read(%pD2, %zd@%Ld)\n", | ||
497 | file, count, (long long) pos); | ||
498 | |||
499 | result = 0; | ||
500 | if (!count) | ||
501 | goto out; | ||
502 | |||
503 | mutex_lock(&inode->i_mutex); | ||
504 | result = nfs_sync_mapping(mapping); | ||
505 | if (result) | ||
506 | goto out_unlock; | ||
507 | |||
508 | task_io_account_read(count); | ||
509 | |||
510 | result = -ENOMEM; | ||
449 | dreq = nfs_direct_req_alloc(); | 511 | dreq = nfs_direct_req_alloc(); |
450 | if (dreq == NULL) | 512 | if (dreq == NULL) |
451 | goto out; | 513 | goto out_unlock; |
452 | 514 | ||
453 | dreq->inode = inode; | 515 | dreq->inode = inode; |
454 | dreq->bytes_left = iov_length(iov, nr_segs); | 516 | dreq->bytes_left = iov_length(iov, nr_segs); |
@@ -464,20 +526,26 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
464 | 526 | ||
465 | NFS_I(inode)->read_io += iov_length(iov, nr_segs); | 527 | NFS_I(inode)->read_io += iov_length(iov, nr_segs); |
466 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio); | 528 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos, uio); |
467 | if (!result) | 529 | |
530 | mutex_unlock(&inode->i_mutex); | ||
531 | |||
532 | if (!result) { | ||
468 | result = nfs_direct_wait(dreq); | 533 | result = nfs_direct_wait(dreq); |
534 | if (result > 0) | ||
535 | iocb->ki_pos = pos + result; | ||
536 | } | ||
537 | |||
538 | nfs_direct_req_release(dreq); | ||
539 | return result; | ||
540 | |||
469 | out_release: | 541 | out_release: |
470 | nfs_direct_req_release(dreq); | 542 | nfs_direct_req_release(dreq); |
543 | out_unlock: | ||
544 | mutex_unlock(&inode->i_mutex); | ||
471 | out: | 545 | out: |
472 | return result; | 546 | return result; |
473 | } | 547 | } |
474 | 548 | ||
475 | static void nfs_inode_dio_write_done(struct inode *inode) | ||
476 | { | ||
477 | nfs_zap_mapping(inode, inode->i_mapping); | ||
478 | inode_dio_done(inode); | ||
479 | } | ||
480 | |||
481 | #if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) | 549 | #if IS_ENABLED(CONFIG_NFS_V3) || IS_ENABLED(CONFIG_NFS_V4) |
482 | static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | 550 | static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) |
483 | { | 551 | { |
@@ -593,8 +661,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work) | |||
593 | nfs_direct_write_reschedule(dreq); | 661 | nfs_direct_write_reschedule(dreq); |
594 | break; | 662 | break; |
595 | default: | 663 | default: |
596 | nfs_inode_dio_write_done(dreq->inode); | 664 | nfs_direct_complete(dreq, true); |
597 | nfs_direct_complete(dreq); | ||
598 | } | 665 | } |
599 | } | 666 | } |
600 | 667 | ||
@@ -610,8 +677,7 @@ static void nfs_direct_write_schedule_work(struct work_struct *work) | |||
610 | 677 | ||
611 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) | 678 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) |
612 | { | 679 | { |
613 | nfs_inode_dio_write_done(inode); | 680 | nfs_direct_complete(dreq, true); |
614 | nfs_direct_complete(dreq); | ||
615 | } | 681 | } |
616 | #endif | 682 | #endif |
617 | 683 | ||
@@ -842,93 +908,6 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq, | |||
842 | return 0; | 908 | return 0; |
843 | } | 909 | } |
844 | 910 | ||
845 | static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | ||
846 | unsigned long nr_segs, loff_t pos, | ||
847 | size_t count, bool uio) | ||
848 | { | ||
849 | ssize_t result = -ENOMEM; | ||
850 | struct inode *inode = iocb->ki_filp->f_mapping->host; | ||
851 | struct nfs_direct_req *dreq; | ||
852 | struct nfs_lock_context *l_ctx; | ||
853 | |||
854 | dreq = nfs_direct_req_alloc(); | ||
855 | if (!dreq) | ||
856 | goto out; | ||
857 | |||
858 | dreq->inode = inode; | ||
859 | dreq->bytes_left = count; | ||
860 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | ||
861 | l_ctx = nfs_get_lock_context(dreq->ctx); | ||
862 | if (IS_ERR(l_ctx)) { | ||
863 | result = PTR_ERR(l_ctx); | ||
864 | goto out_release; | ||
865 | } | ||
866 | dreq->l_ctx = l_ctx; | ||
867 | if (!is_sync_kiocb(iocb)) | ||
868 | dreq->iocb = iocb; | ||
869 | |||
870 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio); | ||
871 | if (!result) | ||
872 | result = nfs_direct_wait(dreq); | ||
873 | out_release: | ||
874 | nfs_direct_req_release(dreq); | ||
875 | out: | ||
876 | return result; | ||
877 | } | ||
878 | |||
879 | /** | ||
880 | * nfs_file_direct_read - file direct read operation for NFS files | ||
881 | * @iocb: target I/O control block | ||
882 | * @iov: vector of user buffers into which to read data | ||
883 | * @nr_segs: size of iov vector | ||
884 | * @pos: byte offset in file where reading starts | ||
885 | * | ||
886 | * We use this function for direct reads instead of calling | ||
887 | * generic_file_aio_read() in order to avoid gfar's check to see if | ||
888 | * the request starts before the end of the file. For that check | ||
889 | * to work, we must generate a GETATTR before each direct read, and | ||
890 | * even then there is a window between the GETATTR and the subsequent | ||
891 | * READ where the file size could change. Our preference is simply | ||
892 | * to do all reads the application wants, and the server will take | ||
893 | * care of managing the end of file boundary. | ||
894 | * | ||
895 | * This function also eliminates unnecessarily updating the file's | ||
896 | * atime locally, as the NFS server sets the file's atime, and this | ||
897 | * client must read the updated atime from the server back into its | ||
898 | * cache. | ||
899 | */ | ||
900 | ssize_t nfs_file_direct_read(struct kiocb *iocb, const struct iovec *iov, | ||
901 | unsigned long nr_segs, loff_t pos, bool uio) | ||
902 | { | ||
903 | ssize_t retval = -EINVAL; | ||
904 | struct file *file = iocb->ki_filp; | ||
905 | struct address_space *mapping = file->f_mapping; | ||
906 | size_t count; | ||
907 | |||
908 | count = iov_length(iov, nr_segs); | ||
909 | nfs_add_stats(mapping->host, NFSIOS_DIRECTREADBYTES, count); | ||
910 | |||
911 | dfprintk(FILE, "NFS: direct read(%pD2, %zd@%Ld)\n", | ||
912 | file, count, (long long) pos); | ||
913 | |||
914 | retval = 0; | ||
915 | if (!count) | ||
916 | goto out; | ||
917 | |||
918 | retval = nfs_sync_mapping(mapping); | ||
919 | if (retval) | ||
920 | goto out; | ||
921 | |||
922 | task_io_account_read(count); | ||
923 | |||
924 | retval = nfs_direct_read(iocb, iov, nr_segs, pos, uio); | ||
925 | if (retval > 0) | ||
926 | iocb->ki_pos = pos + retval; | ||
927 | |||
928 | out: | ||
929 | return retval; | ||
930 | } | ||
931 | |||
932 | /** | 911 | /** |
933 | * nfs_file_direct_write - file direct write operation for NFS files | 912 | * nfs_file_direct_write - file direct write operation for NFS files |
934 | * @iocb: target I/O control block | 913 | * @iocb: target I/O control block |
@@ -954,46 +933,96 @@ out: | |||
954 | ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, | 933 | ssize_t nfs_file_direct_write(struct kiocb *iocb, const struct iovec *iov, |
955 | unsigned long nr_segs, loff_t pos, bool uio) | 934 | unsigned long nr_segs, loff_t pos, bool uio) |
956 | { | 935 | { |
957 | ssize_t retval = -EINVAL; | 936 | ssize_t result = -EINVAL; |
958 | struct file *file = iocb->ki_filp; | 937 | struct file *file = iocb->ki_filp; |
959 | struct address_space *mapping = file->f_mapping; | 938 | struct address_space *mapping = file->f_mapping; |
939 | struct inode *inode = mapping->host; | ||
940 | struct nfs_direct_req *dreq; | ||
941 | struct nfs_lock_context *l_ctx; | ||
942 | loff_t end; | ||
960 | size_t count; | 943 | size_t count; |
961 | 944 | ||
962 | count = iov_length(iov, nr_segs); | 945 | count = iov_length(iov, nr_segs); |
946 | end = (pos + count - 1) >> PAGE_CACHE_SHIFT; | ||
947 | |||
963 | nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); | 948 | nfs_add_stats(mapping->host, NFSIOS_DIRECTWRITTENBYTES, count); |
964 | 949 | ||
965 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", | 950 | dfprintk(FILE, "NFS: direct write(%pD2, %zd@%Ld)\n", |
966 | file, count, (long long) pos); | 951 | file, count, (long long) pos); |
967 | 952 | ||
968 | retval = generic_write_checks(file, &pos, &count, 0); | 953 | result = generic_write_checks(file, &pos, &count, 0); |
969 | if (retval) | 954 | if (result) |
970 | goto out; | 955 | goto out; |
971 | 956 | ||
972 | retval = -EINVAL; | 957 | result = -EINVAL; |
973 | if ((ssize_t) count < 0) | 958 | if ((ssize_t) count < 0) |
974 | goto out; | 959 | goto out; |
975 | retval = 0; | 960 | result = 0; |
976 | if (!count) | 961 | if (!count) |
977 | goto out; | 962 | goto out; |
978 | 963 | ||
979 | retval = nfs_sync_mapping(mapping); | 964 | mutex_lock(&inode->i_mutex); |
980 | if (retval) | 965 | |
981 | goto out; | 966 | result = nfs_sync_mapping(mapping); |
967 | if (result) | ||
968 | goto out_unlock; | ||
969 | |||
970 | if (mapping->nrpages) { | ||
971 | result = invalidate_inode_pages2_range(mapping, | ||
972 | pos >> PAGE_CACHE_SHIFT, end); | ||
973 | if (result) | ||
974 | goto out_unlock; | ||
975 | } | ||
982 | 976 | ||
983 | task_io_account_write(count); | 977 | task_io_account_write(count); |
984 | 978 | ||
985 | retval = nfs_direct_write(iocb, iov, nr_segs, pos, count, uio); | 979 | result = -ENOMEM; |
986 | if (retval > 0) { | 980 | dreq = nfs_direct_req_alloc(); |
987 | struct inode *inode = mapping->host; | 981 | if (!dreq) |
982 | goto out_unlock; | ||
988 | 983 | ||
989 | iocb->ki_pos = pos + retval; | 984 | dreq->inode = inode; |
990 | spin_lock(&inode->i_lock); | 985 | dreq->bytes_left = count; |
991 | if (i_size_read(inode) < iocb->ki_pos) | 986 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
992 | i_size_write(inode, iocb->ki_pos); | 987 | l_ctx = nfs_get_lock_context(dreq->ctx); |
993 | spin_unlock(&inode->i_lock); | 988 | if (IS_ERR(l_ctx)) { |
989 | result = PTR_ERR(l_ctx); | ||
990 | goto out_release; | ||
991 | } | ||
992 | dreq->l_ctx = l_ctx; | ||
993 | if (!is_sync_kiocb(iocb)) | ||
994 | dreq->iocb = iocb; | ||
995 | |||
996 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, uio); | ||
997 | |||
998 | if (mapping->nrpages) { | ||
999 | invalidate_inode_pages2_range(mapping, | ||
1000 | pos >> PAGE_CACHE_SHIFT, end); | ||
994 | } | 1001 | } |
1002 | |||
1003 | mutex_unlock(&inode->i_mutex); | ||
1004 | |||
1005 | if (!result) { | ||
1006 | result = nfs_direct_wait(dreq); | ||
1007 | if (result > 0) { | ||
1008 | struct inode *inode = mapping->host; | ||
1009 | |||
1010 | iocb->ki_pos = pos + result; | ||
1011 | spin_lock(&inode->i_lock); | ||
1012 | if (i_size_read(inode) < iocb->ki_pos) | ||
1013 | i_size_write(inode, iocb->ki_pos); | ||
1014 | spin_unlock(&inode->i_lock); | ||
1015 | } | ||
1016 | } | ||
1017 | nfs_direct_req_release(dreq); | ||
1018 | return result; | ||
1019 | |||
1020 | out_release: | ||
1021 | nfs_direct_req_release(dreq); | ||
1022 | out_unlock: | ||
1023 | mutex_unlock(&inode->i_mutex); | ||
995 | out: | 1024 | out: |
996 | return retval; | 1025 | return result; |
997 | } | 1026 | } |
998 | 1027 | ||
999 | /** | 1028 | /** |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index e2fcacf07de3..5bb790a69c71 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -354,7 +354,7 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, | |||
354 | struct page *page; | 354 | struct page *page; |
355 | int once_thru = 0; | 355 | int once_thru = 0; |
356 | 356 | ||
357 | dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%ld), %u@%lld)\n", | 357 | dfprintk(PAGECACHE, "NFS: write_begin(%pD2(%lu), %u@%lld)\n", |
358 | file, mapping->host->i_ino, len, (long long) pos); | 358 | file, mapping->host->i_ino, len, (long long) pos); |
359 | 359 | ||
360 | start: | 360 | start: |
@@ -395,7 +395,7 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, | |||
395 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 395 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
396 | int status; | 396 | int status; |
397 | 397 | ||
398 | dfprintk(PAGECACHE, "NFS: write_end(%pD2(%ld), %u@%lld)\n", | 398 | dfprintk(PAGECACHE, "NFS: write_end(%pD2(%lu), %u@%lld)\n", |
399 | file, mapping->host->i_ino, len, (long long) pos); | 399 | file, mapping->host->i_ino, len, (long long) pos); |
400 | 400 | ||
401 | /* | 401 | /* |
@@ -585,7 +585,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
585 | int ret = VM_FAULT_NOPAGE; | 585 | int ret = VM_FAULT_NOPAGE; |
586 | struct address_space *mapping; | 586 | struct address_space *mapping; |
587 | 587 | ||
588 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%pD2(%ld), offset %lld)\n", | 588 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%pD2(%lu), offset %lld)\n", |
589 | filp, filp->f_mapping->host->i_ino, | 589 | filp, filp->f_mapping->host->i_ino, |
590 | (long long)page_offset(page)); | 590 | (long long)page_offset(page)); |
591 | 591 | ||
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 00ad1c2b217d..28a0a3cbd3b7 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -458,9 +458,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
458 | unlock_new_inode(inode); | 458 | unlock_new_inode(inode); |
459 | } else | 459 | } else |
460 | nfs_refresh_inode(inode, fattr); | 460 | nfs_refresh_inode(inode, fattr); |
461 | dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", | 461 | dprintk("NFS: nfs_fhget(%s/%Lu fh_crc=0x%08x ct=%d)\n", |
462 | inode->i_sb->s_id, | 462 | inode->i_sb->s_id, |
463 | (long long)NFS_FILEID(inode), | 463 | (unsigned long long)NFS_FILEID(inode), |
464 | nfs_display_fhandle_hash(fh), | 464 | nfs_display_fhandle_hash(fh), |
465 | atomic_read(&inode->i_count)); | 465 | atomic_read(&inode->i_count)); |
466 | 466 | ||
@@ -870,8 +870,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
870 | struct nfs_fattr *fattr = NULL; | 870 | struct nfs_fattr *fattr = NULL; |
871 | struct nfs_inode *nfsi = NFS_I(inode); | 871 | struct nfs_inode *nfsi = NFS_I(inode); |
872 | 872 | ||
873 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 873 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Lu)\n", |
874 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 874 | inode->i_sb->s_id, (unsigned long long)NFS_FILEID(inode)); |
875 | 875 | ||
876 | trace_nfs_revalidate_inode_enter(inode); | 876 | trace_nfs_revalidate_inode_enter(inode); |
877 | 877 | ||
@@ -895,9 +895,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
895 | 895 | ||
896 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label); | 896 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label); |
897 | if (status != 0) { | 897 | if (status != 0) { |
898 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 898 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) getattr failed, error=%d\n", |
899 | inode->i_sb->s_id, | 899 | inode->i_sb->s_id, |
900 | (long long)NFS_FILEID(inode), status); | 900 | (unsigned long long)NFS_FILEID(inode), status); |
901 | if (status == -ESTALE) { | 901 | if (status == -ESTALE) { |
902 | nfs_zap_caches(inode); | 902 | nfs_zap_caches(inode); |
903 | if (!S_ISDIR(inode->i_mode)) | 903 | if (!S_ISDIR(inode->i_mode)) |
@@ -908,9 +908,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
908 | 908 | ||
909 | status = nfs_refresh_inode(inode, fattr); | 909 | status = nfs_refresh_inode(inode, fattr); |
910 | if (status) { | 910 | if (status) { |
911 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 911 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) refresh failed, error=%d\n", |
912 | inode->i_sb->s_id, | 912 | inode->i_sb->s_id, |
913 | (long long)NFS_FILEID(inode), status); | 913 | (unsigned long long)NFS_FILEID(inode), status); |
914 | goto err_out; | 914 | goto err_out; |
915 | } | 915 | } |
916 | 916 | ||
@@ -919,9 +919,9 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
919 | 919 | ||
920 | nfs_setsecurity(inode, fattr, label); | 920 | nfs_setsecurity(inode, fattr, label); |
921 | 921 | ||
922 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", | 922 | dfprintk(PAGECACHE, "NFS: (%s/%Lu) revalidation complete\n", |
923 | inode->i_sb->s_id, | 923 | inode->i_sb->s_id, |
924 | (long long)NFS_FILEID(inode)); | 924 | (unsigned long long)NFS_FILEID(inode)); |
925 | 925 | ||
926 | err_out: | 926 | err_out: |
927 | nfs4_label_free(label); | 927 | nfs4_label_free(label); |
@@ -977,16 +977,17 @@ static int nfs_invalidate_mapping(struct inode *inode, struct address_space *map | |||
977 | if (ret < 0) | 977 | if (ret < 0) |
978 | return ret; | 978 | return ret; |
979 | } | 979 | } |
980 | spin_lock(&inode->i_lock); | 980 | if (S_ISDIR(inode->i_mode)) { |
981 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | 981 | spin_lock(&inode->i_lock); |
982 | if (S_ISDIR(inode->i_mode)) | ||
983 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 982 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
984 | spin_unlock(&inode->i_lock); | 983 | spin_unlock(&inode->i_lock); |
984 | } | ||
985 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); | 985 | nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE); |
986 | nfs_fscache_wait_on_invalidate(inode); | 986 | nfs_fscache_wait_on_invalidate(inode); |
987 | 987 | ||
988 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 988 | dfprintk(PAGECACHE, "NFS: (%s/%Lu) data cache invalidated\n", |
989 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 989 | inode->i_sb->s_id, |
990 | (unsigned long long)NFS_FILEID(inode)); | ||
990 | return 0; | 991 | return 0; |
991 | } | 992 | } |
992 | 993 | ||
@@ -1007,6 +1008,7 @@ static bool nfs_mapping_need_revalidate_inode(struct inode *inode) | |||
1007 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | 1008 | int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) |
1008 | { | 1009 | { |
1009 | struct nfs_inode *nfsi = NFS_I(inode); | 1010 | struct nfs_inode *nfsi = NFS_I(inode); |
1011 | unsigned long *bitlock = &nfsi->flags; | ||
1010 | int ret = 0; | 1012 | int ret = 0; |
1011 | 1013 | ||
1012 | /* swapfiles are not supposed to be shared. */ | 1014 | /* swapfiles are not supposed to be shared. */ |
@@ -1018,12 +1020,46 @@ int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | |||
1018 | if (ret < 0) | 1020 | if (ret < 0) |
1019 | goto out; | 1021 | goto out; |
1020 | } | 1022 | } |
1021 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { | 1023 | |
1022 | trace_nfs_invalidate_mapping_enter(inode); | 1024 | /* |
1023 | ret = nfs_invalidate_mapping(inode, mapping); | 1025 | * We must clear NFS_INO_INVALID_DATA first to ensure that |
1024 | trace_nfs_invalidate_mapping_exit(inode, ret); | 1026 | * invalidations that come in while we're shooting down the mappings |
1027 | * are respected. But, that leaves a race window where one revalidator | ||
1028 | * can clear the flag, and then another checks it before the mapping | ||
1029 | * gets invalidated. Fix that by serializing access to this part of | ||
1030 | * the function. | ||
1031 | * | ||
1032 | * At the same time, we need to allow other tasks to see whether we | ||
1033 | * might be in the middle of invalidating the pages, so we only set | ||
1034 | * the bit lock here if it looks like we're going to be doing that. | ||
1035 | */ | ||
1036 | for (;;) { | ||
1037 | ret = wait_on_bit(bitlock, NFS_INO_INVALIDATING, | ||
1038 | nfs_wait_bit_killable, TASK_KILLABLE); | ||
1039 | if (ret) | ||
1040 | goto out; | ||
1041 | spin_lock(&inode->i_lock); | ||
1042 | if (test_bit(NFS_INO_INVALIDATING, bitlock)) { | ||
1043 | spin_unlock(&inode->i_lock); | ||
1044 | continue; | ||
1045 | } | ||
1046 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) | ||
1047 | break; | ||
1048 | spin_unlock(&inode->i_lock); | ||
1049 | goto out; | ||
1025 | } | 1050 | } |
1026 | 1051 | ||
1052 | set_bit(NFS_INO_INVALIDATING, bitlock); | ||
1053 | smp_wmb(); | ||
1054 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | ||
1055 | spin_unlock(&inode->i_lock); | ||
1056 | trace_nfs_invalidate_mapping_enter(inode); | ||
1057 | ret = nfs_invalidate_mapping(inode, mapping); | ||
1058 | trace_nfs_invalidate_mapping_exit(inode, ret); | ||
1059 | |||
1060 | clear_bit_unlock(NFS_INO_INVALIDATING, bitlock); | ||
1061 | smp_mb__after_clear_bit(); | ||
1062 | wake_up_bit(bitlock, NFS_INO_INVALIDATING); | ||
1027 | out: | 1063 | out: |
1028 | return ret; | 1064 | return ret; |
1029 | } | 1065 | } |
@@ -1282,12 +1318,28 @@ static int nfs_inode_attrs_need_update(const struct inode *inode, const struct n | |||
1282 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); | 1318 | ((long)nfsi->attr_gencount - (long)nfs_read_attr_generation_counter() > 0); |
1283 | } | 1319 | } |
1284 | 1320 | ||
1321 | /* | ||
1322 | * Don't trust the change_attribute, mtime, ctime or size if | ||
1323 | * a pnfs LAYOUTCOMMIT is outstanding | ||
1324 | */ | ||
1325 | static void nfs_inode_attrs_handle_layoutcommit(struct inode *inode, | ||
1326 | struct nfs_fattr *fattr) | ||
1327 | { | ||
1328 | if (pnfs_layoutcommit_outstanding(inode)) | ||
1329 | fattr->valid &= ~(NFS_ATTR_FATTR_CHANGE | | ||
1330 | NFS_ATTR_FATTR_MTIME | | ||
1331 | NFS_ATTR_FATTR_CTIME | | ||
1332 | NFS_ATTR_FATTR_SIZE); | ||
1333 | } | ||
1334 | |||
1285 | static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) | 1335 | static int nfs_refresh_inode_locked(struct inode *inode, struct nfs_fattr *fattr) |
1286 | { | 1336 | { |
1287 | int ret; | 1337 | int ret; |
1288 | 1338 | ||
1289 | trace_nfs_refresh_inode_enter(inode); | 1339 | trace_nfs_refresh_inode_enter(inode); |
1290 | 1340 | ||
1341 | nfs_inode_attrs_handle_layoutcommit(inode, fattr); | ||
1342 | |||
1291 | if (nfs_inode_attrs_need_update(inode, fattr)) | 1343 | if (nfs_inode_attrs_need_update(inode, fattr)) |
1292 | ret = nfs_update_inode(inode, fattr); | 1344 | ret = nfs_update_inode(inode, fattr); |
1293 | else | 1345 | else |
@@ -1434,7 +1486,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1434 | unsigned long now = jiffies; | 1486 | unsigned long now = jiffies; |
1435 | unsigned long save_cache_validity; | 1487 | unsigned long save_cache_validity; |
1436 | 1488 | ||
1437 | dfprintk(VFS, "NFS: %s(%s/%ld fh_crc=0x%08x ct=%d info=0x%x)\n", | 1489 | dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%x)\n", |
1438 | __func__, inode->i_sb->s_id, inode->i_ino, | 1490 | __func__, inode->i_sb->s_id, inode->i_ino, |
1439 | nfs_display_fhandle_hash(NFS_FH(inode)), | 1491 | nfs_display_fhandle_hash(NFS_FH(inode)), |
1440 | atomic_read(&inode->i_count), fattr->valid); | 1492 | atomic_read(&inode->i_count), fattr->valid); |
@@ -1455,7 +1507,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1455 | /* | 1507 | /* |
1456 | * Big trouble! The inode has become a different object. | 1508 | * Big trouble! The inode has become a different object. |
1457 | */ | 1509 | */ |
1458 | printk(KERN_DEBUG "NFS: %s: inode %ld mode changed, %07o to %07o\n", | 1510 | printk(KERN_DEBUG "NFS: %s: inode %lu mode changed, %07o to %07o\n", |
1459 | __func__, inode->i_ino, inode->i_mode, fattr->mode); | 1511 | __func__, inode->i_ino, inode->i_mode, fattr->mode); |
1460 | goto out_err; | 1512 | goto out_err; |
1461 | } | 1513 | } |
@@ -1517,8 +1569,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1517 | if (new_isize != cur_isize) { | 1569 | if (new_isize != cur_isize) { |
1518 | /* Do we perhaps have any outstanding writes, or has | 1570 | /* Do we perhaps have any outstanding writes, or has |
1519 | * the file grown beyond our last write? */ | 1571 | * the file grown beyond our last write? */ |
1520 | if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) || | 1572 | if ((nfsi->npages == 0) || new_isize > cur_isize) { |
1521 | new_isize > cur_isize) { | ||
1522 | i_size_write(inode, new_isize); | 1573 | i_size_write(inode, new_isize); |
1523 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1574 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1524 | } | 1575 | } |
@@ -1641,10 +1692,6 @@ struct inode *nfs_alloc_inode(struct super_block *sb) | |||
1641 | return NULL; | 1692 | return NULL; |
1642 | nfsi->flags = 0UL; | 1693 | nfsi->flags = 0UL; |
1643 | nfsi->cache_validity = 0UL; | 1694 | nfsi->cache_validity = 0UL; |
1644 | #ifdef CONFIG_NFS_V3_ACL | ||
1645 | nfsi->acl_access = ERR_PTR(-EAGAIN); | ||
1646 | nfsi->acl_default = ERR_PTR(-EAGAIN); | ||
1647 | #endif | ||
1648 | #if IS_ENABLED(CONFIG_NFS_V4) | 1695 | #if IS_ENABLED(CONFIG_NFS_V4) |
1649 | nfsi->nfs4_acl = NULL; | 1696 | nfsi->nfs4_acl = NULL; |
1650 | #endif /* CONFIG_NFS_V4 */ | 1697 | #endif /* CONFIG_NFS_V4 */ |
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 4a1aafba6a20..871d6eda8dba 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c | |||
@@ -10,179 +10,7 @@ | |||
10 | 10 | ||
11 | #define NFSDBG_FACILITY NFSDBG_PROC | 11 | #define NFSDBG_FACILITY NFSDBG_PROC |
12 | 12 | ||
13 | ssize_t nfs3_listxattr(struct dentry *dentry, char *buffer, size_t size) | 13 | struct posix_acl *nfs3_get_acl(struct inode *inode, int type) |
14 | { | ||
15 | struct inode *inode = dentry->d_inode; | ||
16 | struct posix_acl *acl; | ||
17 | int pos=0, len=0; | ||
18 | |||
19 | # define output(s) do { \ | ||
20 | if (pos + sizeof(s) <= size) { \ | ||
21 | memcpy(buffer + pos, s, sizeof(s)); \ | ||
22 | pos += sizeof(s); \ | ||
23 | } \ | ||
24 | len += sizeof(s); \ | ||
25 | } while(0) | ||
26 | |||
27 | acl = nfs3_proc_getacl(inode, ACL_TYPE_ACCESS); | ||
28 | if (IS_ERR(acl)) | ||
29 | return PTR_ERR(acl); | ||
30 | if (acl) { | ||
31 | output("system.posix_acl_access"); | ||
32 | posix_acl_release(acl); | ||
33 | } | ||
34 | |||
35 | if (S_ISDIR(inode->i_mode)) { | ||
36 | acl = nfs3_proc_getacl(inode, ACL_TYPE_DEFAULT); | ||
37 | if (IS_ERR(acl)) | ||
38 | return PTR_ERR(acl); | ||
39 | if (acl) { | ||
40 | output("system.posix_acl_default"); | ||
41 | posix_acl_release(acl); | ||
42 | } | ||
43 | } | ||
44 | |||
45 | # undef output | ||
46 | |||
47 | if (!buffer || len <= size) | ||
48 | return len; | ||
49 | return -ERANGE; | ||
50 | } | ||
51 | |||
52 | ssize_t nfs3_getxattr(struct dentry *dentry, const char *name, | ||
53 | void *buffer, size_t size) | ||
54 | { | ||
55 | struct inode *inode = dentry->d_inode; | ||
56 | struct posix_acl *acl; | ||
57 | int type, error = 0; | ||
58 | |||
59 | if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) | ||
60 | type = ACL_TYPE_ACCESS; | ||
61 | else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) | ||
62 | type = ACL_TYPE_DEFAULT; | ||
63 | else | ||
64 | return -EOPNOTSUPP; | ||
65 | |||
66 | acl = nfs3_proc_getacl(inode, type); | ||
67 | if (IS_ERR(acl)) | ||
68 | return PTR_ERR(acl); | ||
69 | else if (acl) { | ||
70 | if (type == ACL_TYPE_ACCESS && acl->a_count == 0) | ||
71 | error = -ENODATA; | ||
72 | else | ||
73 | error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); | ||
74 | posix_acl_release(acl); | ||
75 | } else | ||
76 | error = -ENODATA; | ||
77 | |||
78 | return error; | ||
79 | } | ||
80 | |||
81 | int nfs3_setxattr(struct dentry *dentry, const char *name, | ||
82 | const void *value, size_t size, int flags) | ||
83 | { | ||
84 | struct inode *inode = dentry->d_inode; | ||
85 | struct posix_acl *acl; | ||
86 | int type, error; | ||
87 | |||
88 | if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) | ||
89 | type = ACL_TYPE_ACCESS; | ||
90 | else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) | ||
91 | type = ACL_TYPE_DEFAULT; | ||
92 | else | ||
93 | return -EOPNOTSUPP; | ||
94 | |||
95 | acl = posix_acl_from_xattr(&init_user_ns, value, size); | ||
96 | if (IS_ERR(acl)) | ||
97 | return PTR_ERR(acl); | ||
98 | error = nfs3_proc_setacl(inode, type, acl); | ||
99 | posix_acl_release(acl); | ||
100 | |||
101 | return error; | ||
102 | } | ||
103 | |||
104 | int nfs3_removexattr(struct dentry *dentry, const char *name) | ||
105 | { | ||
106 | struct inode *inode = dentry->d_inode; | ||
107 | int type; | ||
108 | |||
109 | if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) | ||
110 | type = ACL_TYPE_ACCESS; | ||
111 | else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) | ||
112 | type = ACL_TYPE_DEFAULT; | ||
113 | else | ||
114 | return -EOPNOTSUPP; | ||
115 | |||
116 | return nfs3_proc_setacl(inode, type, NULL); | ||
117 | } | ||
118 | |||
119 | static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi) | ||
120 | { | ||
121 | if (!IS_ERR(nfsi->acl_access)) { | ||
122 | posix_acl_release(nfsi->acl_access); | ||
123 | nfsi->acl_access = ERR_PTR(-EAGAIN); | ||
124 | } | ||
125 | if (!IS_ERR(nfsi->acl_default)) { | ||
126 | posix_acl_release(nfsi->acl_default); | ||
127 | nfsi->acl_default = ERR_PTR(-EAGAIN); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | void nfs3_forget_cached_acls(struct inode *inode) | ||
132 | { | ||
133 | dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id, | ||
134 | inode->i_ino); | ||
135 | spin_lock(&inode->i_lock); | ||
136 | __nfs3_forget_cached_acls(NFS_I(inode)); | ||
137 | spin_unlock(&inode->i_lock); | ||
138 | } | ||
139 | |||
140 | static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type) | ||
141 | { | ||
142 | struct nfs_inode *nfsi = NFS_I(inode); | ||
143 | struct posix_acl *acl = ERR_PTR(-EINVAL); | ||
144 | |||
145 | spin_lock(&inode->i_lock); | ||
146 | switch(type) { | ||
147 | case ACL_TYPE_ACCESS: | ||
148 | acl = nfsi->acl_access; | ||
149 | break; | ||
150 | |||
151 | case ACL_TYPE_DEFAULT: | ||
152 | acl = nfsi->acl_default; | ||
153 | break; | ||
154 | |||
155 | default: | ||
156 | goto out; | ||
157 | } | ||
158 | if (IS_ERR(acl)) | ||
159 | acl = ERR_PTR(-EAGAIN); | ||
160 | else | ||
161 | acl = posix_acl_dup(acl); | ||
162 | out: | ||
163 | spin_unlock(&inode->i_lock); | ||
164 | dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id, | ||
165 | inode->i_ino, type, acl); | ||
166 | return acl; | ||
167 | } | ||
168 | |||
169 | static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl, | ||
170 | struct posix_acl *dfacl) | ||
171 | { | ||
172 | struct nfs_inode *nfsi = NFS_I(inode); | ||
173 | |||
174 | dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id, | ||
175 | inode->i_ino, acl, dfacl); | ||
176 | spin_lock(&inode->i_lock); | ||
177 | __nfs3_forget_cached_acls(NFS_I(inode)); | ||
178 | if (!IS_ERR(acl)) | ||
179 | nfsi->acl_access = posix_acl_dup(acl); | ||
180 | if (!IS_ERR(dfacl)) | ||
181 | nfsi->acl_default = posix_acl_dup(dfacl); | ||
182 | spin_unlock(&inode->i_lock); | ||
183 | } | ||
184 | |||
185 | struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | ||
186 | { | 14 | { |
187 | struct nfs_server *server = NFS_SERVER(inode); | 15 | struct nfs_server *server = NFS_SERVER(inode); |
188 | struct page *pages[NFSACL_MAXPAGES] = { }; | 16 | struct page *pages[NFSACL_MAXPAGES] = { }; |
@@ -198,7 +26,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | |||
198 | .rpc_argp = &args, | 26 | .rpc_argp = &args, |
199 | .rpc_resp = &res, | 27 | .rpc_resp = &res, |
200 | }; | 28 | }; |
201 | struct posix_acl *acl; | ||
202 | int status, count; | 29 | int status, count; |
203 | 30 | ||
204 | if (!nfs_server_capable(inode, NFS_CAP_ACLS)) | 31 | if (!nfs_server_capable(inode, NFS_CAP_ACLS)) |
@@ -207,10 +34,6 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | |||
207 | status = nfs_revalidate_inode(server, inode); | 34 | status = nfs_revalidate_inode(server, inode); |
208 | if (status < 0) | 35 | if (status < 0) |
209 | return ERR_PTR(status); | 36 | return ERR_PTR(status); |
210 | acl = nfs3_get_cached_acl(inode, type); | ||
211 | if (acl != ERR_PTR(-EAGAIN)) | ||
212 | return acl; | ||
213 | acl = NULL; | ||
214 | 37 | ||
215 | /* | 38 | /* |
216 | * Only get the access acl when explicitly requested: We don't | 39 | * Only get the access acl when explicitly requested: We don't |
@@ -257,40 +80,41 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) | |||
257 | } | 80 | } |
258 | 81 | ||
259 | if (res.acl_access != NULL) { | 82 | if (res.acl_access != NULL) { |
260 | if (posix_acl_equiv_mode(res.acl_access, NULL) == 0) { | 83 | if ((posix_acl_equiv_mode(res.acl_access, NULL) == 0) || |
84 | res.acl_access->a_count == 0) { | ||
261 | posix_acl_release(res.acl_access); | 85 | posix_acl_release(res.acl_access); |
262 | res.acl_access = NULL; | 86 | res.acl_access = NULL; |
263 | } | 87 | } |
264 | } | 88 | } |
265 | nfs3_cache_acls(inode, | ||
266 | (res.mask & NFS_ACL) ? res.acl_access : ERR_PTR(-EINVAL), | ||
267 | (res.mask & NFS_DFACL) ? res.acl_default : ERR_PTR(-EINVAL)); | ||
268 | 89 | ||
269 | switch(type) { | 90 | if (res.mask & NFS_ACL) |
270 | case ACL_TYPE_ACCESS: | 91 | set_cached_acl(inode, ACL_TYPE_ACCESS, res.acl_access); |
271 | acl = res.acl_access; | 92 | else |
272 | res.acl_access = NULL; | 93 | forget_cached_acl(inode, ACL_TYPE_ACCESS); |
273 | break; | ||
274 | 94 | ||
275 | case ACL_TYPE_DEFAULT: | 95 | if (res.mask & NFS_DFACL) |
276 | acl = res.acl_default; | 96 | set_cached_acl(inode, ACL_TYPE_DEFAULT, res.acl_default); |
277 | res.acl_default = NULL; | 97 | else |
98 | forget_cached_acl(inode, ACL_TYPE_DEFAULT); | ||
99 | |||
100 | nfs_free_fattr(res.fattr); | ||
101 | if (type == ACL_TYPE_ACCESS) { | ||
102 | posix_acl_release(res.acl_default); | ||
103 | return res.acl_access; | ||
104 | } else { | ||
105 | posix_acl_release(res.acl_access); | ||
106 | return res.acl_default; | ||
278 | } | 107 | } |
279 | 108 | ||
280 | getout: | 109 | getout: |
281 | posix_acl_release(res.acl_access); | 110 | posix_acl_release(res.acl_access); |
282 | posix_acl_release(res.acl_default); | 111 | posix_acl_release(res.acl_default); |
283 | nfs_free_fattr(res.fattr); | 112 | nfs_free_fattr(res.fattr); |
284 | 113 | return ERR_PTR(status); | |
285 | if (status != 0) { | ||
286 | posix_acl_release(acl); | ||
287 | acl = ERR_PTR(status); | ||
288 | } | ||
289 | return acl; | ||
290 | } | 114 | } |
291 | 115 | ||
292 | static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | 116 | static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, |
293 | struct posix_acl *dfacl) | 117 | struct posix_acl *dfacl) |
294 | { | 118 | { |
295 | struct nfs_server *server = NFS_SERVER(inode); | 119 | struct nfs_server *server = NFS_SERVER(inode); |
296 | struct nfs_fattr *fattr; | 120 | struct nfs_fattr *fattr; |
@@ -353,7 +177,8 @@ static int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, | |||
353 | switch (status) { | 177 | switch (status) { |
354 | case 0: | 178 | case 0: |
355 | status = nfs_refresh_inode(inode, fattr); | 179 | status = nfs_refresh_inode(inode, fattr); |
356 | nfs3_cache_acls(inode, acl, dfacl); | 180 | set_cached_acl(inode, ACL_TYPE_ACCESS, acl); |
181 | set_cached_acl(inode, ACL_TYPE_DEFAULT, dfacl); | ||
357 | break; | 182 | break; |
358 | case -EPFNOSUPPORT: | 183 | case -EPFNOSUPPORT: |
359 | case -EPROTONOSUPPORT: | 184 | case -EPROTONOSUPPORT: |
@@ -373,40 +198,43 @@ out: | |||
373 | return status; | 198 | return status; |
374 | } | 199 | } |
375 | 200 | ||
376 | int nfs3_proc_setacl(struct inode *inode, int type, struct posix_acl *acl) | 201 | int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, |
202 | struct posix_acl *dfacl) | ||
203 | { | ||
204 | int ret; | ||
205 | ret = __nfs3_proc_setacls(inode, acl, dfacl); | ||
206 | return (ret == -EOPNOTSUPP) ? 0 : ret; | ||
207 | |||
208 | } | ||
209 | |||
210 | int nfs3_set_acl(struct inode *inode, struct posix_acl *acl, int type) | ||
377 | { | 211 | { |
378 | struct posix_acl *alloc = NULL, *dfacl = NULL; | 212 | struct posix_acl *alloc = NULL, *dfacl = NULL; |
379 | int status; | 213 | int status; |
380 | 214 | ||
381 | if (S_ISDIR(inode->i_mode)) { | 215 | if (S_ISDIR(inode->i_mode)) { |
382 | switch(type) { | 216 | switch(type) { |
383 | case ACL_TYPE_ACCESS: | 217 | case ACL_TYPE_ACCESS: |
384 | alloc = dfacl = nfs3_proc_getacl(inode, | 218 | alloc = dfacl = get_acl(inode, ACL_TYPE_DEFAULT); |
385 | ACL_TYPE_DEFAULT); | 219 | if (IS_ERR(alloc)) |
386 | if (IS_ERR(alloc)) | 220 | goto fail; |
387 | goto fail; | 221 | break; |
388 | break; | ||
389 | |||
390 | case ACL_TYPE_DEFAULT: | ||
391 | dfacl = acl; | ||
392 | alloc = acl = nfs3_proc_getacl(inode, | ||
393 | ACL_TYPE_ACCESS); | ||
394 | if (IS_ERR(alloc)) | ||
395 | goto fail; | ||
396 | break; | ||
397 | 222 | ||
398 | default: | 223 | case ACL_TYPE_DEFAULT: |
399 | return -EINVAL; | 224 | dfacl = acl; |
225 | alloc = acl = get_acl(inode, ACL_TYPE_ACCESS); | ||
226 | if (IS_ERR(alloc)) | ||
227 | goto fail; | ||
228 | break; | ||
400 | } | 229 | } |
401 | } else if (type != ACL_TYPE_ACCESS) | 230 | } |
402 | return -EINVAL; | ||
403 | 231 | ||
404 | if (acl == NULL) { | 232 | if (acl == NULL) { |
405 | alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); | 233 | alloc = acl = posix_acl_from_mode(inode->i_mode, GFP_KERNEL); |
406 | if (IS_ERR(alloc)) | 234 | if (IS_ERR(alloc)) |
407 | goto fail; | 235 | goto fail; |
408 | } | 236 | } |
409 | status = nfs3_proc_setacls(inode, acl, dfacl); | 237 | status = __nfs3_proc_setacls(inode, acl, dfacl); |
410 | posix_acl_release(alloc); | 238 | posix_acl_release(alloc); |
411 | return status; | 239 | return status; |
412 | 240 | ||
@@ -414,27 +242,8 @@ fail: | |||
414 | return PTR_ERR(alloc); | 242 | return PTR_ERR(alloc); |
415 | } | 243 | } |
416 | 244 | ||
417 | int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, | 245 | const struct xattr_handler *nfs3_xattr_handlers[] = { |
418 | umode_t mode) | 246 | &posix_acl_access_xattr_handler, |
419 | { | 247 | &posix_acl_default_xattr_handler, |
420 | struct posix_acl *dfacl, *acl; | 248 | NULL, |
421 | int error = 0; | 249 | }; |
422 | |||
423 | dfacl = nfs3_proc_getacl(dir, ACL_TYPE_DEFAULT); | ||
424 | if (IS_ERR(dfacl)) { | ||
425 | error = PTR_ERR(dfacl); | ||
426 | return (error == -EOPNOTSUPP) ? 0 : error; | ||
427 | } | ||
428 | if (!dfacl) | ||
429 | return 0; | ||
430 | acl = posix_acl_dup(dfacl); | ||
431 | error = posix_acl_create(&acl, GFP_KERNEL, &mode); | ||
432 | if (error < 0) | ||
433 | goto out_release_dfacl; | ||
434 | error = nfs3_proc_setacls(inode, acl, S_ISDIR(inode->i_mode) ? | ||
435 | dfacl : NULL); | ||
436 | posix_acl_release(acl); | ||
437 | out_release_dfacl: | ||
438 | posix_acl_release(dfacl); | ||
439 | return error; | ||
440 | } | ||
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 01b6f6a49d16..aa9bc973f36a 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -317,8 +317,8 @@ static int | |||
317 | nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 317 | nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
318 | int flags) | 318 | int flags) |
319 | { | 319 | { |
320 | struct posix_acl *default_acl, *acl; | ||
320 | struct nfs3_createdata *data; | 321 | struct nfs3_createdata *data; |
321 | umode_t mode = sattr->ia_mode; | ||
322 | int status = -ENOMEM; | 322 | int status = -ENOMEM; |
323 | 323 | ||
324 | dprintk("NFS call create %pd\n", dentry); | 324 | dprintk("NFS call create %pd\n", dentry); |
@@ -340,7 +340,9 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
340 | data->arg.create.verifier[1] = cpu_to_be32(current->pid); | 340 | data->arg.create.verifier[1] = cpu_to_be32(current->pid); |
341 | } | 341 | } |
342 | 342 | ||
343 | sattr->ia_mode &= ~current_umask(); | 343 | status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl); |
344 | if (status) | ||
345 | goto out; | ||
344 | 346 | ||
345 | for (;;) { | 347 | for (;;) { |
346 | status = nfs3_do_create(dir, dentry, data); | 348 | status = nfs3_do_create(dir, dentry, data); |
@@ -366,7 +368,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
366 | } | 368 | } |
367 | 369 | ||
368 | if (status != 0) | 370 | if (status != 0) |
369 | goto out; | 371 | goto out_release_acls; |
370 | 372 | ||
371 | /* When we created the file with exclusive semantics, make | 373 | /* When we created the file with exclusive semantics, make |
372 | * sure we set the attributes afterwards. */ | 374 | * sure we set the attributes afterwards. */ |
@@ -385,9 +387,14 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
385 | nfs_post_op_update_inode(dentry->d_inode, data->res.fattr); | 387 | nfs_post_op_update_inode(dentry->d_inode, data->res.fattr); |
386 | dprintk("NFS reply setattr (post-create): %d\n", status); | 388 | dprintk("NFS reply setattr (post-create): %d\n", status); |
387 | if (status != 0) | 389 | if (status != 0) |
388 | goto out; | 390 | goto out_release_acls; |
389 | } | 391 | } |
390 | status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); | 392 | |
393 | status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl); | ||
394 | |||
395 | out_release_acls: | ||
396 | posix_acl_release(acl); | ||
397 | posix_acl_release(default_acl); | ||
391 | out: | 398 | out: |
392 | nfs3_free_createdata(data); | 399 | nfs3_free_createdata(data); |
393 | dprintk("NFS reply create: %d\n", status); | 400 | dprintk("NFS reply create: %d\n", status); |
@@ -572,18 +579,20 @@ out: | |||
572 | static int | 579 | static int |
573 | nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | 580 | nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) |
574 | { | 581 | { |
582 | struct posix_acl *default_acl, *acl; | ||
575 | struct nfs3_createdata *data; | 583 | struct nfs3_createdata *data; |
576 | umode_t mode = sattr->ia_mode; | ||
577 | int status = -ENOMEM; | 584 | int status = -ENOMEM; |
578 | 585 | ||
579 | dprintk("NFS call mkdir %pd\n", dentry); | 586 | dprintk("NFS call mkdir %pd\n", dentry); |
580 | 587 | ||
581 | sattr->ia_mode &= ~current_umask(); | ||
582 | |||
583 | data = nfs3_alloc_createdata(); | 588 | data = nfs3_alloc_createdata(); |
584 | if (data == NULL) | 589 | if (data == NULL) |
585 | goto out; | 590 | goto out; |
586 | 591 | ||
592 | status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl); | ||
593 | if (status) | ||
594 | goto out; | ||
595 | |||
587 | data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR]; | 596 | data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR]; |
588 | data->arg.mkdir.fh = NFS_FH(dir); | 597 | data->arg.mkdir.fh = NFS_FH(dir); |
589 | data->arg.mkdir.name = dentry->d_name.name; | 598 | data->arg.mkdir.name = dentry->d_name.name; |
@@ -592,9 +601,13 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | |||
592 | 601 | ||
593 | status = nfs3_do_create(dir, dentry, data); | 602 | status = nfs3_do_create(dir, dentry, data); |
594 | if (status != 0) | 603 | if (status != 0) |
595 | goto out; | 604 | goto out_release_acls; |
596 | 605 | ||
597 | status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); | 606 | status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl); |
607 | |||
608 | out_release_acls: | ||
609 | posix_acl_release(acl); | ||
610 | posix_acl_release(default_acl); | ||
598 | out: | 611 | out: |
599 | nfs3_free_createdata(data); | 612 | nfs3_free_createdata(data); |
600 | dprintk("NFS reply mkdir: %d\n", status); | 613 | dprintk("NFS reply mkdir: %d\n", status); |
@@ -691,19 +704,21 @@ static int | |||
691 | nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 704 | nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
692 | dev_t rdev) | 705 | dev_t rdev) |
693 | { | 706 | { |
707 | struct posix_acl *default_acl, *acl; | ||
694 | struct nfs3_createdata *data; | 708 | struct nfs3_createdata *data; |
695 | umode_t mode = sattr->ia_mode; | ||
696 | int status = -ENOMEM; | 709 | int status = -ENOMEM; |
697 | 710 | ||
698 | dprintk("NFS call mknod %pd %u:%u\n", dentry, | 711 | dprintk("NFS call mknod %pd %u:%u\n", dentry, |
699 | MAJOR(rdev), MINOR(rdev)); | 712 | MAJOR(rdev), MINOR(rdev)); |
700 | 713 | ||
701 | sattr->ia_mode &= ~current_umask(); | ||
702 | |||
703 | data = nfs3_alloc_createdata(); | 714 | data = nfs3_alloc_createdata(); |
704 | if (data == NULL) | 715 | if (data == NULL) |
705 | goto out; | 716 | goto out; |
706 | 717 | ||
718 | status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl); | ||
719 | if (status) | ||
720 | goto out; | ||
721 | |||
707 | data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD]; | 722 | data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD]; |
708 | data->arg.mknod.fh = NFS_FH(dir); | 723 | data->arg.mknod.fh = NFS_FH(dir); |
709 | data->arg.mknod.name = dentry->d_name.name; | 724 | data->arg.mknod.name = dentry->d_name.name; |
@@ -731,8 +746,13 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
731 | 746 | ||
732 | status = nfs3_do_create(dir, dentry, data); | 747 | status = nfs3_do_create(dir, dentry, data); |
733 | if (status != 0) | 748 | if (status != 0) |
734 | goto out; | 749 | goto out_release_acls; |
735 | status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode); | 750 | |
751 | status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl); | ||
752 | |||
753 | out_release_acls: | ||
754 | posix_acl_release(acl); | ||
755 | posix_acl_release(default_acl); | ||
736 | out: | 756 | out: |
737 | nfs3_free_createdata(data); | 757 | nfs3_free_createdata(data); |
738 | dprintk("NFS reply mknod: %d\n", status); | 758 | dprintk("NFS reply mknod: %d\n", status); |
@@ -904,20 +924,28 @@ static const struct inode_operations nfs3_dir_inode_operations = { | |||
904 | .permission = nfs_permission, | 924 | .permission = nfs_permission, |
905 | .getattr = nfs_getattr, | 925 | .getattr = nfs_getattr, |
906 | .setattr = nfs_setattr, | 926 | .setattr = nfs_setattr, |
907 | .listxattr = nfs3_listxattr, | 927 | #ifdef CONFIG_NFS_V3_ACL |
908 | .getxattr = nfs3_getxattr, | 928 | .listxattr = generic_listxattr, |
909 | .setxattr = nfs3_setxattr, | 929 | .getxattr = generic_getxattr, |
910 | .removexattr = nfs3_removexattr, | 930 | .setxattr = generic_setxattr, |
931 | .removexattr = generic_removexattr, | ||
932 | .get_acl = nfs3_get_acl, | ||
933 | .set_acl = nfs3_set_acl, | ||
934 | #endif | ||
911 | }; | 935 | }; |
912 | 936 | ||
913 | static const struct inode_operations nfs3_file_inode_operations = { | 937 | static const struct inode_operations nfs3_file_inode_operations = { |
914 | .permission = nfs_permission, | 938 | .permission = nfs_permission, |
915 | .getattr = nfs_getattr, | 939 | .getattr = nfs_getattr, |
916 | .setattr = nfs_setattr, | 940 | .setattr = nfs_setattr, |
917 | .listxattr = nfs3_listxattr, | 941 | #ifdef CONFIG_NFS_V3_ACL |
918 | .getxattr = nfs3_getxattr, | 942 | .listxattr = generic_listxattr, |
919 | .setxattr = nfs3_setxattr, | 943 | .getxattr = generic_getxattr, |
920 | .removexattr = nfs3_removexattr, | 944 | .setxattr = generic_setxattr, |
945 | .removexattr = generic_removexattr, | ||
946 | .get_acl = nfs3_get_acl, | ||
947 | .set_acl = nfs3_set_acl, | ||
948 | #endif | ||
921 | }; | 949 | }; |
922 | 950 | ||
923 | const struct nfs_rpc_ops nfs_v3_clientops = { | 951 | const struct nfs_rpc_ops nfs_v3_clientops = { |
@@ -965,7 +993,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = { | |||
965 | .commit_rpc_prepare = nfs3_proc_commit_rpc_prepare, | 993 | .commit_rpc_prepare = nfs3_proc_commit_rpc_prepare, |
966 | .commit_done = nfs3_commit_done, | 994 | .commit_done = nfs3_commit_done, |
967 | .lock = nfs3_proc_lock, | 995 | .lock = nfs3_proc_lock, |
968 | .clear_acl_cache = nfs3_forget_cached_acls, | 996 | .clear_acl_cache = forget_all_cached_acls, |
969 | .close_context = nfs_close_context, | 997 | .close_context = nfs_close_context, |
970 | .have_delegation = nfs3_have_delegation, | 998 | .have_delegation = nfs3_have_delegation, |
971 | .return_delegation = nfs3_return_delegation, | 999 | .return_delegation = nfs3_return_delegation, |
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c index cc471c725230..d6a98949af19 100644 --- a/fs/nfs/nfs3super.c +++ b/fs/nfs/nfs3super.c | |||
@@ -12,6 +12,9 @@ static struct nfs_subversion nfs_v3 = { | |||
12 | .rpc_vers = &nfs_version3, | 12 | .rpc_vers = &nfs_version3, |
13 | .rpc_ops = &nfs_v3_clientops, | 13 | .rpc_ops = &nfs_v3_clientops, |
14 | .sops = &nfs_sops, | 14 | .sops = &nfs_sops, |
15 | #ifdef CONFIG_NFS_V3_ACL | ||
16 | .xattr = nfs3_xattr_handlers, | ||
17 | #endif | ||
15 | }; | 18 | }; |
16 | 19 | ||
17 | static int __init init_nfs_v3(void) | 20 | static int __init init_nfs_v3(void) |
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 5609edc742a0..a5b27c2d9689 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -270,6 +270,7 @@ static inline struct nfs4_session *nfs4_get_session(const struct nfs_server *ser | |||
270 | extern int nfs41_setup_sequence(struct nfs4_session *session, | 270 | extern int nfs41_setup_sequence(struct nfs4_session *session, |
271 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, | 271 | struct nfs4_sequence_args *args, struct nfs4_sequence_res *res, |
272 | struct rpc_task *task); | 272 | struct rpc_task *task); |
273 | extern int nfs41_sequence_done(struct rpc_task *, struct nfs4_sequence_res *); | ||
273 | extern int nfs4_proc_create_session(struct nfs_client *, struct rpc_cred *); | 274 | extern int nfs4_proc_create_session(struct nfs_client *, struct rpc_cred *); |
274 | extern int nfs4_proc_destroy_session(struct nfs4_session *, struct rpc_cred *); | 275 | extern int nfs4_proc_destroy_session(struct nfs4_session *, struct rpc_cred *); |
275 | extern int nfs4_proc_get_lease_time(struct nfs_client *clp, | 276 | extern int nfs4_proc_get_lease_time(struct nfs_client *clp, |
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index b4a160a405ce..860ad26a5590 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/sunrpc/auth.h> | 10 | #include <linux/sunrpc/auth.h> |
11 | #include <linux/sunrpc/xprt.h> | 11 | #include <linux/sunrpc/xprt.h> |
12 | #include <linux/sunrpc/bc_xprt.h> | 12 | #include <linux/sunrpc/bc_xprt.h> |
13 | #include <linux/sunrpc/rpc_pipe_fs.h> | ||
13 | #include "internal.h" | 14 | #include "internal.h" |
14 | #include "callback.h" | 15 | #include "callback.h" |
15 | #include "delegation.h" | 16 | #include "delegation.h" |
@@ -169,7 +170,7 @@ void nfs41_shutdown_client(struct nfs_client *clp) | |||
169 | void nfs40_shutdown_client(struct nfs_client *clp) | 170 | void nfs40_shutdown_client(struct nfs_client *clp) |
170 | { | 171 | { |
171 | if (clp->cl_slot_tbl) { | 172 | if (clp->cl_slot_tbl) { |
172 | nfs4_release_slot_table(clp->cl_slot_tbl); | 173 | nfs4_shutdown_slot_table(clp->cl_slot_tbl); |
173 | kfree(clp->cl_slot_tbl); | 174 | kfree(clp->cl_slot_tbl); |
174 | } | 175 | } |
175 | } | 176 | } |
@@ -370,6 +371,7 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp, | |||
370 | __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags); | 371 | __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags); |
371 | __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); | 372 | __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); |
372 | __set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags); | 373 | __set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags); |
374 | |||
373 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I); | 375 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_GSS_KRB5I); |
374 | if (error == -EINVAL) | 376 | if (error == -EINVAL) |
375 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX); | 377 | error = nfs_create_rpc_client(clp, timeparms, RPC_AUTH_UNIX); |
@@ -409,13 +411,11 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp, | |||
409 | error = nfs4_discover_server_trunking(clp, &old); | 411 | error = nfs4_discover_server_trunking(clp, &old); |
410 | if (error < 0) | 412 | if (error < 0) |
411 | goto error; | 413 | goto error; |
412 | nfs_put_client(clp); | ||
413 | if (clp != old) { | ||
414 | clp->cl_preserve_clid = true; | ||
415 | clp = old; | ||
416 | } | ||
417 | 414 | ||
418 | return clp; | 415 | if (clp != old) |
416 | clp->cl_preserve_clid = true; | ||
417 | nfs_put_client(clp); | ||
418 | return old; | ||
419 | 419 | ||
420 | error: | 420 | error: |
421 | nfs_mark_client_ready(clp, error); | 421 | nfs_mark_client_ready(clp, error); |
@@ -493,9 +493,10 @@ int nfs40_walk_client_list(struct nfs_client *new, | |||
493 | prev = pos; | 493 | prev = pos; |
494 | 494 | ||
495 | status = nfs_wait_client_init_complete(pos); | 495 | status = nfs_wait_client_init_complete(pos); |
496 | spin_lock(&nn->nfs_client_lock); | ||
497 | if (status < 0) | 496 | if (status < 0) |
498 | continue; | 497 | goto out; |
498 | status = -NFS4ERR_STALE_CLIENTID; | ||
499 | spin_lock(&nn->nfs_client_lock); | ||
499 | } | 500 | } |
500 | if (pos->cl_cons_state != NFS_CS_READY) | 501 | if (pos->cl_cons_state != NFS_CS_READY) |
501 | continue; | 502 | continue; |
@@ -633,7 +634,8 @@ int nfs41_walk_client_list(struct nfs_client *new, | |||
633 | } | 634 | } |
634 | spin_lock(&nn->nfs_client_lock); | 635 | spin_lock(&nn->nfs_client_lock); |
635 | if (status < 0) | 636 | if (status < 0) |
636 | continue; | 637 | break; |
638 | status = -NFS4ERR_STALE_CLIENTID; | ||
637 | } | 639 | } |
638 | if (pos->cl_cons_state != NFS_CS_READY) | 640 | if (pos->cl_cons_state != NFS_CS_READY) |
639 | continue; | 641 | continue; |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index b86464ba25e1..12c8132ad408 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -91,10 +91,10 @@ static void filelayout_reset_write(struct nfs_write_data *data) | |||
91 | 91 | ||
92 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { | 92 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { |
93 | dprintk("%s Reset task %5u for i/o through MDS " | 93 | dprintk("%s Reset task %5u for i/o through MDS " |
94 | "(req %s/%lld, %u bytes @ offset %llu)\n", __func__, | 94 | "(req %s/%llu, %u bytes @ offset %llu)\n", __func__, |
95 | data->task.tk_pid, | 95 | data->task.tk_pid, |
96 | hdr->inode->i_sb->s_id, | 96 | hdr->inode->i_sb->s_id, |
97 | (long long)NFS_FILEID(hdr->inode), | 97 | (unsigned long long)NFS_FILEID(hdr->inode), |
98 | data->args.count, | 98 | data->args.count, |
99 | (unsigned long long)data->args.offset); | 99 | (unsigned long long)data->args.offset); |
100 | 100 | ||
@@ -112,10 +112,10 @@ static void filelayout_reset_read(struct nfs_read_data *data) | |||
112 | 112 | ||
113 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { | 113 | if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) { |
114 | dprintk("%s Reset task %5u for i/o through MDS " | 114 | dprintk("%s Reset task %5u for i/o through MDS " |
115 | "(req %s/%lld, %u bytes @ offset %llu)\n", __func__, | 115 | "(req %s/%llu, %u bytes @ offset %llu)\n", __func__, |
116 | data->task.tk_pid, | 116 | data->task.tk_pid, |
117 | hdr->inode->i_sb->s_id, | 117 | hdr->inode->i_sb->s_id, |
118 | (long long)NFS_FILEID(hdr->inode), | 118 | (unsigned long long)NFS_FILEID(hdr->inode), |
119 | data->args.count, | 119 | data->args.count, |
120 | (unsigned long long)data->args.offset); | 120 | (unsigned long long)data->args.offset); |
121 | 121 | ||
@@ -335,8 +335,10 @@ static void filelayout_read_call_done(struct rpc_task *task, void *data) | |||
335 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); | 335 | dprintk("--> %s task->tk_status %d\n", __func__, task->tk_status); |
336 | 336 | ||
337 | if (test_bit(NFS_IOHDR_REDO, &rdata->header->flags) && | 337 | if (test_bit(NFS_IOHDR_REDO, &rdata->header->flags) && |
338 | task->tk_status == 0) | 338 | task->tk_status == 0) { |
339 | nfs41_sequence_done(task, &rdata->res.seq_res); | ||
339 | return; | 340 | return; |
341 | } | ||
340 | 342 | ||
341 | /* Note this may cause RPC to be resent */ | 343 | /* Note this may cause RPC to be resent */ |
342 | rdata->header->mds_ops->rpc_call_done(task, data); | 344 | rdata->header->mds_ops->rpc_call_done(task, data); |
@@ -442,8 +444,10 @@ static void filelayout_write_call_done(struct rpc_task *task, void *data) | |||
442 | struct nfs_write_data *wdata = data; | 444 | struct nfs_write_data *wdata = data; |
443 | 445 | ||
444 | if (test_bit(NFS_IOHDR_REDO, &wdata->header->flags) && | 446 | if (test_bit(NFS_IOHDR_REDO, &wdata->header->flags) && |
445 | task->tk_status == 0) | 447 | task->tk_status == 0) { |
448 | nfs41_sequence_done(task, &wdata->res.seq_res); | ||
446 | return; | 449 | return; |
450 | } | ||
447 | 451 | ||
448 | /* Note this may cause RPC to be resent */ | 452 | /* Note this may cause RPC to be resent */ |
449 | wdata->header->mds_ops->rpc_call_done(task, data); | 453 | wdata->header->mds_ops->rpc_call_done(task, data); |
@@ -1216,17 +1220,17 @@ static void filelayout_recover_commit_reqs(struct list_head *dst, | |||
1216 | struct pnfs_commit_bucket *b; | 1220 | struct pnfs_commit_bucket *b; |
1217 | int i; | 1221 | int i; |
1218 | 1222 | ||
1219 | /* NOTE cinfo->lock is NOT held, relying on fact that this is | 1223 | spin_lock(cinfo->lock); |
1220 | * only called on single thread per dreq. | ||
1221 | * Can't take the lock because need to do pnfs_put_lseg | ||
1222 | */ | ||
1223 | for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { | 1224 | for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) { |
1224 | if (transfer_commit_list(&b->written, dst, cinfo, 0)) { | 1225 | if (transfer_commit_list(&b->written, dst, cinfo, 0)) { |
1226 | spin_unlock(cinfo->lock); | ||
1225 | pnfs_put_lseg(b->wlseg); | 1227 | pnfs_put_lseg(b->wlseg); |
1226 | b->wlseg = NULL; | 1228 | b->wlseg = NULL; |
1229 | spin_lock(cinfo->lock); | ||
1227 | } | 1230 | } |
1228 | } | 1231 | } |
1229 | cinfo->ds->nwritten = 0; | 1232 | cinfo->ds->nwritten = 0; |
1233 | spin_unlock(cinfo->lock); | ||
1230 | } | 1234 | } |
1231 | 1235 | ||
1232 | static unsigned int | 1236 | static unsigned int |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index c7c295e556ed..efac602edb37 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
@@ -95,7 +95,7 @@ same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2) | |||
95 | b6 = (struct sockaddr_in6 *)addr2; | 95 | b6 = (struct sockaddr_in6 *)addr2; |
96 | 96 | ||
97 | /* LINKLOCAL addresses must have matching scope_id */ | 97 | /* LINKLOCAL addresses must have matching scope_id */ |
98 | if (ipv6_addr_scope(&a6->sin6_addr) == | 98 | if (ipv6_addr_src_scope(&a6->sin6_addr) == |
99 | IPV6_ADDR_SCOPE_LINKLOCAL && | 99 | IPV6_ADDR_SCOPE_LINKLOCAL && |
100 | a6->sin6_scope_id != b6->sin6_scope_id) | 100 | a6->sin6_scope_id != b6->sin6_scope_id) |
101 | return false; | 101 | return false; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 15052b81df42..2da6a698b8f7 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -539,7 +539,7 @@ static int nfs40_sequence_done(struct rpc_task *task, | |||
539 | struct nfs4_slot *slot = res->sr_slot; | 539 | struct nfs4_slot *slot = res->sr_slot; |
540 | struct nfs4_slot_table *tbl; | 540 | struct nfs4_slot_table *tbl; |
541 | 541 | ||
542 | if (!RPC_WAS_SENT(task)) | 542 | if (slot == NULL) |
543 | goto out; | 543 | goto out; |
544 | 544 | ||
545 | tbl = slot->table; | 545 | tbl = slot->table; |
@@ -559,15 +559,10 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | |||
559 | { | 559 | { |
560 | struct nfs4_session *session; | 560 | struct nfs4_session *session; |
561 | struct nfs4_slot_table *tbl; | 561 | struct nfs4_slot_table *tbl; |
562 | struct nfs4_slot *slot = res->sr_slot; | ||
562 | bool send_new_highest_used_slotid = false; | 563 | bool send_new_highest_used_slotid = false; |
563 | 564 | ||
564 | if (!res->sr_slot) { | 565 | tbl = slot->table; |
565 | /* just wake up the next guy waiting since | ||
566 | * we may have not consumed a slot after all */ | ||
567 | dprintk("%s: No slot\n", __func__); | ||
568 | return; | ||
569 | } | ||
570 | tbl = res->sr_slot->table; | ||
571 | session = tbl->session; | 566 | session = tbl->session; |
572 | 567 | ||
573 | spin_lock(&tbl->slot_tbl_lock); | 568 | spin_lock(&tbl->slot_tbl_lock); |
@@ -577,11 +572,11 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res) | |||
577 | if (tbl->highest_used_slotid > tbl->target_highest_slotid) | 572 | if (tbl->highest_used_slotid > tbl->target_highest_slotid) |
578 | send_new_highest_used_slotid = true; | 573 | send_new_highest_used_slotid = true; |
579 | 574 | ||
580 | if (nfs41_wake_and_assign_slot(tbl, res->sr_slot)) { | 575 | if (nfs41_wake_and_assign_slot(tbl, slot)) { |
581 | send_new_highest_used_slotid = false; | 576 | send_new_highest_used_slotid = false; |
582 | goto out_unlock; | 577 | goto out_unlock; |
583 | } | 578 | } |
584 | nfs4_free_slot(tbl, res->sr_slot); | 579 | nfs4_free_slot(tbl, slot); |
585 | 580 | ||
586 | if (tbl->highest_used_slotid != NFS4_NO_SLOT) | 581 | if (tbl->highest_used_slotid != NFS4_NO_SLOT) |
587 | send_new_highest_used_slotid = false; | 582 | send_new_highest_used_slotid = false; |
@@ -592,19 +587,20 @@ out_unlock: | |||
592 | nfs41_server_notify_highest_slotid_update(session->clp); | 587 | nfs41_server_notify_highest_slotid_update(session->clp); |
593 | } | 588 | } |
594 | 589 | ||
595 | static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) | 590 | int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res) |
596 | { | 591 | { |
597 | struct nfs4_session *session; | 592 | struct nfs4_session *session; |
598 | struct nfs4_slot *slot; | 593 | struct nfs4_slot *slot = res->sr_slot; |
599 | struct nfs_client *clp; | 594 | struct nfs_client *clp; |
600 | bool interrupted = false; | 595 | bool interrupted = false; |
601 | int ret = 1; | 596 | int ret = 1; |
602 | 597 | ||
598 | if (slot == NULL) | ||
599 | goto out_noaction; | ||
603 | /* don't increment the sequence number if the task wasn't sent */ | 600 | /* don't increment the sequence number if the task wasn't sent */ |
604 | if (!RPC_WAS_SENT(task)) | 601 | if (!RPC_WAS_SENT(task)) |
605 | goto out; | 602 | goto out; |
606 | 603 | ||
607 | slot = res->sr_slot; | ||
608 | session = slot->table->session; | 604 | session = slot->table->session; |
609 | 605 | ||
610 | if (slot->interrupted) { | 606 | if (slot->interrupted) { |
@@ -679,6 +675,7 @@ out: | |||
679 | /* The session may be reset by one of the error handlers. */ | 675 | /* The session may be reset by one of the error handlers. */ |
680 | dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); | 676 | dprintk("%s: Error %d free the slot \n", __func__, res->sr_status); |
681 | nfs41_sequence_free_slot(res); | 677 | nfs41_sequence_free_slot(res); |
678 | out_noaction: | ||
682 | return ret; | 679 | return ret; |
683 | retry_nowait: | 680 | retry_nowait: |
684 | if (rpc_restart_call_prepare(task)) { | 681 | if (rpc_restart_call_prepare(task)) { |
@@ -692,6 +689,7 @@ out_retry: | |||
692 | rpc_delay(task, NFS4_POLL_RETRY_MAX); | 689 | rpc_delay(task, NFS4_POLL_RETRY_MAX); |
693 | return 0; | 690 | return 0; |
694 | } | 691 | } |
692 | EXPORT_SYMBOL_GPL(nfs41_sequence_done); | ||
695 | 693 | ||
696 | static int nfs4_sequence_done(struct rpc_task *task, | 694 | static int nfs4_sequence_done(struct rpc_task *task, |
697 | struct nfs4_sequence_res *res) | 695 | struct nfs4_sequence_res *res) |
@@ -1622,15 +1620,15 @@ static void nfs4_open_confirm_prepare(struct rpc_task *task, void *calldata) | |||
1622 | { | 1620 | { |
1623 | struct nfs4_opendata *data = calldata; | 1621 | struct nfs4_opendata *data = calldata; |
1624 | 1622 | ||
1625 | nfs40_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, | 1623 | nfs40_setup_sequence(data->o_arg.server, &data->c_arg.seq_args, |
1626 | &data->o_res.seq_res, task); | 1624 | &data->c_res.seq_res, task); |
1627 | } | 1625 | } |
1628 | 1626 | ||
1629 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) | 1627 | static void nfs4_open_confirm_done(struct rpc_task *task, void *calldata) |
1630 | { | 1628 | { |
1631 | struct nfs4_opendata *data = calldata; | 1629 | struct nfs4_opendata *data = calldata; |
1632 | 1630 | ||
1633 | nfs40_sequence_done(task, &data->o_res.seq_res); | 1631 | nfs40_sequence_done(task, &data->c_res.seq_res); |
1634 | 1632 | ||
1635 | data->rpc_status = task->tk_status; | 1633 | data->rpc_status = task->tk_status; |
1636 | if (data->rpc_status == 0) { | 1634 | if (data->rpc_status == 0) { |
@@ -1688,7 +1686,7 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data) | |||
1688 | }; | 1686 | }; |
1689 | int status; | 1687 | int status; |
1690 | 1688 | ||
1691 | nfs4_init_sequence(&data->o_arg.seq_args, &data->o_res.seq_res, 1); | 1689 | nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1); |
1692 | kref_get(&data->kref); | 1690 | kref_get(&data->kref); |
1693 | data->rpc_done = 0; | 1691 | data->rpc_done = 0; |
1694 | data->rpc_status = 0; | 1692 | data->rpc_status = 0; |
@@ -2744,7 +2742,8 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f | |||
2744 | NFS_CAP_OWNER_GROUP|NFS_CAP_ATIME| | 2742 | NFS_CAP_OWNER_GROUP|NFS_CAP_ATIME| |
2745 | NFS_CAP_CTIME|NFS_CAP_MTIME| | 2743 | NFS_CAP_CTIME|NFS_CAP_MTIME| |
2746 | NFS_CAP_SECURITY_LABEL); | 2744 | NFS_CAP_SECURITY_LABEL); |
2747 | if (res.attr_bitmask[0] & FATTR4_WORD0_ACL) | 2745 | if (res.attr_bitmask[0] & FATTR4_WORD0_ACL && |
2746 | res.acl_bitmask & ACL4_SUPPORT_ALLOW_ACL) | ||
2748 | server->caps |= NFS_CAP_ACLS; | 2747 | server->caps |= NFS_CAP_ACLS; |
2749 | if (res.has_links != 0) | 2748 | if (res.has_links != 0) |
2750 | server->caps |= NFS_CAP_HARDLINKS; | 2749 | server->caps |= NFS_CAP_HARDLINKS; |
@@ -4321,9 +4320,7 @@ static int nfs4_proc_renew(struct nfs_client *clp, struct rpc_cred *cred) | |||
4321 | 4320 | ||
4322 | static inline int nfs4_server_supports_acls(struct nfs_server *server) | 4321 | static inline int nfs4_server_supports_acls(struct nfs_server *server) |
4323 | { | 4322 | { |
4324 | return (server->caps & NFS_CAP_ACLS) | 4323 | return server->caps & NFS_CAP_ACLS; |
4325 | && (server->acl_bitmask & ACL4_SUPPORT_ALLOW_ACL) | ||
4326 | && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL); | ||
4327 | } | 4324 | } |
4328 | 4325 | ||
4329 | /* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that | 4326 | /* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that |
@@ -7409,9 +7406,9 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
7409 | struct nfs_server *server = NFS_SERVER(inode); | 7406 | struct nfs_server *server = NFS_SERVER(inode); |
7410 | struct pnfs_layout_hdr *lo; | 7407 | struct pnfs_layout_hdr *lo; |
7411 | struct nfs4_state *state = NULL; | 7408 | struct nfs4_state *state = NULL; |
7412 | unsigned long timeo, giveup; | 7409 | unsigned long timeo, now, giveup; |
7413 | 7410 | ||
7414 | dprintk("--> %s\n", __func__); | 7411 | dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status); |
7415 | 7412 | ||
7416 | if (!nfs41_sequence_done(task, &lgp->res.seq_res)) | 7413 | if (!nfs41_sequence_done(task, &lgp->res.seq_res)) |
7417 | goto out; | 7414 | goto out; |
@@ -7419,12 +7416,38 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) | |||
7419 | switch (task->tk_status) { | 7416 | switch (task->tk_status) { |
7420 | case 0: | 7417 | case 0: |
7421 | goto out; | 7418 | goto out; |
7419 | /* | ||
7420 | * NFS4ERR_LAYOUTTRYLATER is a conflict with another client | ||
7421 | * (or clients) writing to the same RAID stripe | ||
7422 | */ | ||
7422 | case -NFS4ERR_LAYOUTTRYLATER: | 7423 | case -NFS4ERR_LAYOUTTRYLATER: |
7424 | /* | ||
7425 | * NFS4ERR_RECALLCONFLICT is when conflict with self (must recall | ||
7426 | * existing layout before getting a new one). | ||
7427 | */ | ||
7423 | case -NFS4ERR_RECALLCONFLICT: | 7428 | case -NFS4ERR_RECALLCONFLICT: |
7424 | timeo = rpc_get_timeout(task->tk_client); | 7429 | timeo = rpc_get_timeout(task->tk_client); |
7425 | giveup = lgp->args.timestamp + timeo; | 7430 | giveup = lgp->args.timestamp + timeo; |
7426 | if (time_after(giveup, jiffies)) | 7431 | now = jiffies; |
7427 | task->tk_status = -NFS4ERR_DELAY; | 7432 | if (time_after(giveup, now)) { |
7433 | unsigned long delay; | ||
7434 | |||
7435 | /* Delay for: | ||
7436 | * - Not less then NFS4_POLL_RETRY_MIN. | ||
7437 | * - One last time a jiffie before we give up | ||
7438 | * - exponential backoff (time_now minus start_attempt) | ||
7439 | */ | ||
7440 | delay = max_t(unsigned long, NFS4_POLL_RETRY_MIN, | ||
7441 | min((giveup - now - 1), | ||
7442 | now - lgp->args.timestamp)); | ||
7443 | |||
7444 | dprintk("%s: NFS4ERR_RECALLCONFLICT waiting %lu\n", | ||
7445 | __func__, delay); | ||
7446 | rpc_delay(task, delay); | ||
7447 | task->tk_status = 0; | ||
7448 | rpc_restart_call_prepare(task); | ||
7449 | goto out; /* Do not call nfs4_async_handle_error() */ | ||
7450 | } | ||
7428 | break; | 7451 | break; |
7429 | case -NFS4ERR_EXPIRED: | 7452 | case -NFS4ERR_EXPIRED: |
7430 | case -NFS4ERR_BAD_STATEID: | 7453 | case -NFS4ERR_BAD_STATEID: |
@@ -7780,10 +7803,7 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata) | |||
7780 | case -NFS4ERR_BADLAYOUT: /* no layout */ | 7803 | case -NFS4ERR_BADLAYOUT: /* no layout */ |
7781 | case -NFS4ERR_GRACE: /* loca_recalim always false */ | 7804 | case -NFS4ERR_GRACE: /* loca_recalim always false */ |
7782 | task->tk_status = 0; | 7805 | task->tk_status = 0; |
7783 | break; | ||
7784 | case 0: | 7806 | case 0: |
7785 | nfs_post_op_update_inode_force_wcc(data->args.inode, | ||
7786 | data->res.fattr); | ||
7787 | break; | 7807 | break; |
7788 | default: | 7808 | default: |
7789 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { | 7809 | if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) { |
@@ -7798,6 +7818,8 @@ static void nfs4_layoutcommit_release(void *calldata) | |||
7798 | struct nfs4_layoutcommit_data *data = calldata; | 7818 | struct nfs4_layoutcommit_data *data = calldata; |
7799 | 7819 | ||
7800 | pnfs_cleanup_layoutcommit(data); | 7820 | pnfs_cleanup_layoutcommit(data); |
7821 | nfs_post_op_update_inode_force_wcc(data->args.inode, | ||
7822 | data->res.fattr); | ||
7801 | put_rpccred(data->cred); | 7823 | put_rpccred(data->cred); |
7802 | kfree(data); | 7824 | kfree(data); |
7803 | } | 7825 | } |
@@ -7920,7 +7942,7 @@ nfs41_proc_secinfo_no_name(struct nfs_server *server, struct nfs_fh *fhandle, | |||
7920 | switch (err) { | 7942 | switch (err) { |
7921 | case 0: | 7943 | case 0: |
7922 | case -NFS4ERR_WRONGSEC: | 7944 | case -NFS4ERR_WRONGSEC: |
7923 | case -NFS4ERR_NOTSUPP: | 7945 | case -ENOTSUPP: |
7924 | goto out; | 7946 | goto out; |
7925 | default: | 7947 | default: |
7926 | err = nfs4_handle_exception(server, err, &exception); | 7948 | err = nfs4_handle_exception(server, err, &exception); |
@@ -7954,7 +7976,7 @@ nfs41_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
7954 | * Fall back on "guess and check" method if | 7976 | * Fall back on "guess and check" method if |
7955 | * the server doesn't support SECINFO_NO_NAME | 7977 | * the server doesn't support SECINFO_NO_NAME |
7956 | */ | 7978 | */ |
7957 | if (err == -NFS4ERR_WRONGSEC || err == -NFS4ERR_NOTSUPP) { | 7979 | if (err == -NFS4ERR_WRONGSEC || err == -ENOTSUPP) { |
7958 | err = nfs4_find_root_sec(server, fhandle, info); | 7980 | err = nfs4_find_root_sec(server, fhandle, info); |
7959 | goto out_freepage; | 7981 | goto out_freepage; |
7960 | } | 7982 | } |
diff --git a/fs/nfs/nfs4session.c b/fs/nfs/nfs4session.c index cf883c7ae053..e799dc3c3b1d 100644 --- a/fs/nfs/nfs4session.c +++ b/fs/nfs/nfs4session.c | |||
@@ -231,14 +231,23 @@ out: | |||
231 | return ret; | 231 | return ret; |
232 | } | 232 | } |
233 | 233 | ||
234 | /* | ||
235 | * nfs4_release_slot_table - release all slot table entries | ||
236 | */ | ||
237 | static void nfs4_release_slot_table(struct nfs4_slot_table *tbl) | ||
238 | { | ||
239 | nfs4_shrink_slot_table(tbl, 0); | ||
240 | } | ||
241 | |||
234 | /** | 242 | /** |
235 | * nfs4_release_slot_table - release resources attached to a slot table | 243 | * nfs4_shutdown_slot_table - release resources attached to a slot table |
236 | * @tbl: slot table to shut down | 244 | * @tbl: slot table to shut down |
237 | * | 245 | * |
238 | */ | 246 | */ |
239 | void nfs4_release_slot_table(struct nfs4_slot_table *tbl) | 247 | void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl) |
240 | { | 248 | { |
241 | nfs4_shrink_slot_table(tbl, 0); | 249 | nfs4_release_slot_table(tbl); |
250 | rpc_destroy_wait_queue(&tbl->slot_tbl_waitq); | ||
242 | } | 251 | } |
243 | 252 | ||
244 | /** | 253 | /** |
@@ -422,7 +431,7 @@ void nfs41_update_target_slotid(struct nfs4_slot_table *tbl, | |||
422 | spin_unlock(&tbl->slot_tbl_lock); | 431 | spin_unlock(&tbl->slot_tbl_lock); |
423 | } | 432 | } |
424 | 433 | ||
425 | static void nfs4_destroy_session_slot_tables(struct nfs4_session *session) | 434 | static void nfs4_release_session_slot_tables(struct nfs4_session *session) |
426 | { | 435 | { |
427 | nfs4_release_slot_table(&session->fc_slot_table); | 436 | nfs4_release_slot_table(&session->fc_slot_table); |
428 | nfs4_release_slot_table(&session->bc_slot_table); | 437 | nfs4_release_slot_table(&session->bc_slot_table); |
@@ -450,7 +459,7 @@ int nfs4_setup_session_slot_tables(struct nfs4_session *ses) | |||
450 | if (status && tbl->slots == NULL) | 459 | if (status && tbl->slots == NULL) |
451 | /* Fore and back channel share a connection so get | 460 | /* Fore and back channel share a connection so get |
452 | * both slot tables or neither */ | 461 | * both slot tables or neither */ |
453 | nfs4_destroy_session_slot_tables(ses); | 462 | nfs4_release_session_slot_tables(ses); |
454 | return status; | 463 | return status; |
455 | } | 464 | } |
456 | 465 | ||
@@ -470,6 +479,12 @@ struct nfs4_session *nfs4_alloc_session(struct nfs_client *clp) | |||
470 | return session; | 479 | return session; |
471 | } | 480 | } |
472 | 481 | ||
482 | static void nfs4_destroy_session_slot_tables(struct nfs4_session *session) | ||
483 | { | ||
484 | nfs4_shutdown_slot_table(&session->fc_slot_table); | ||
485 | nfs4_shutdown_slot_table(&session->bc_slot_table); | ||
486 | } | ||
487 | |||
473 | void nfs4_destroy_session(struct nfs4_session *session) | 488 | void nfs4_destroy_session(struct nfs4_session *session) |
474 | { | 489 | { |
475 | struct rpc_xprt *xprt; | 490 | struct rpc_xprt *xprt; |
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h index 232306100651..b34ada9bc6a2 100644 --- a/fs/nfs/nfs4session.h +++ b/fs/nfs/nfs4session.h | |||
@@ -74,7 +74,7 @@ enum nfs4_session_state { | |||
74 | 74 | ||
75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, | 75 | extern int nfs4_setup_slot_table(struct nfs4_slot_table *tbl, |
76 | unsigned int max_reqs, const char *queue); | 76 | unsigned int max_reqs, const char *queue); |
77 | extern void nfs4_release_slot_table(struct nfs4_slot_table *tbl); | 77 | extern void nfs4_shutdown_slot_table(struct nfs4_slot_table *tbl); |
78 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); | 78 | extern struct nfs4_slot *nfs4_alloc_slot(struct nfs4_slot_table *tbl); |
79 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); | 79 | extern void nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *slot); |
80 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); | 80 | extern void nfs4_slot_tbl_drain_complete(struct nfs4_slot_table *tbl); |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 059c01b67a71..e5be72518bd7 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1071,7 +1071,7 @@ void nfs_free_seqid(struct nfs_seqid *seqid) | |||
1071 | /* | 1071 | /* |
1072 | * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or | 1072 | * Increment the seqid if the OPEN/OPEN_DOWNGRADE/CLOSE succeeded, or |
1073 | * failed with a seqid incrementing error - | 1073 | * failed with a seqid incrementing error - |
1074 | * see comments nfs_fs.h:seqid_mutating_error() | 1074 | * see comments nfs4.h:seqid_mutating_error() |
1075 | */ | 1075 | */ |
1076 | static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) | 1076 | static void nfs_increment_seqid(int status, struct nfs_seqid *seqid) |
1077 | { | 1077 | { |
@@ -1116,7 +1116,7 @@ void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid) | |||
1116 | /* | 1116 | /* |
1117 | * Increment the seqid if the LOCK/LOCKU succeeded, or | 1117 | * Increment the seqid if the LOCK/LOCKU succeeded, or |
1118 | * failed with a seqid incrementing error - | 1118 | * failed with a seqid incrementing error - |
1119 | * see comments nfs_fs.h:seqid_mutating_error() | 1119 | * see comments nfs4.h:seqid_mutating_error() |
1120 | */ | 1120 | */ |
1121 | void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid) | 1121 | void nfs_increment_lock_seqid(int status, struct nfs_seqid *seqid) |
1122 | { | 1122 | { |
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 65ab0a0ca1c4..808f29574412 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
@@ -77,17 +77,9 @@ static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc) | |||
77 | { | 77 | { |
78 | int ret = nfs_write_inode(inode, wbc); | 78 | int ret = nfs_write_inode(inode, wbc); |
79 | 79 | ||
80 | if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { | 80 | if (ret == 0) |
81 | int status; | 81 | ret = pnfs_layoutcommit_inode(inode, |
82 | bool sync = true; | 82 | wbc->sync_mode == WB_SYNC_ALL); |
83 | |||
84 | if (wbc->sync_mode == WB_SYNC_NONE) | ||
85 | sync = false; | ||
86 | |||
87 | status = pnfs_layoutcommit_inode(inode, sync); | ||
88 | if (status < 0) | ||
89 | return status; | ||
90 | } | ||
91 | return ret; | 83 | return ret; |
92 | } | 84 | } |
93 | 85 | ||
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 5be2868c02f1..72f3bf1754ef 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -3097,7 +3097,8 @@ out_overflow: | |||
3097 | return -EIO; | 3097 | return -EIO; |
3098 | } | 3098 | } |
3099 | 3099 | ||
3100 | static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) | 3100 | static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected, |
3101 | int *nfs_retval) | ||
3101 | { | 3102 | { |
3102 | __be32 *p; | 3103 | __be32 *p; |
3103 | uint32_t opnum; | 3104 | uint32_t opnum; |
@@ -3107,19 +3108,32 @@ static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) | |||
3107 | if (unlikely(!p)) | 3108 | if (unlikely(!p)) |
3108 | goto out_overflow; | 3109 | goto out_overflow; |
3109 | opnum = be32_to_cpup(p++); | 3110 | opnum = be32_to_cpup(p++); |
3110 | if (opnum != expected) { | 3111 | if (unlikely(opnum != expected)) |
3111 | dprintk("nfs: Server returned operation" | 3112 | goto out_bad_operation; |
3112 | " %d but we issued a request for %d\n", | ||
3113 | opnum, expected); | ||
3114 | return -EIO; | ||
3115 | } | ||
3116 | nfserr = be32_to_cpup(p); | 3113 | nfserr = be32_to_cpup(p); |
3117 | if (nfserr != NFS_OK) | 3114 | if (nfserr == NFS_OK) |
3118 | return nfs4_stat_to_errno(nfserr); | 3115 | *nfs_retval = 0; |
3119 | return 0; | 3116 | else |
3117 | *nfs_retval = nfs4_stat_to_errno(nfserr); | ||
3118 | return true; | ||
3119 | out_bad_operation: | ||
3120 | dprintk("nfs: Server returned operation" | ||
3121 | " %d but we issued a request for %d\n", | ||
3122 | opnum, expected); | ||
3123 | *nfs_retval = -EREMOTEIO; | ||
3124 | return false; | ||
3120 | out_overflow: | 3125 | out_overflow: |
3121 | print_overflow_msg(__func__, xdr); | 3126 | print_overflow_msg(__func__, xdr); |
3122 | return -EIO; | 3127 | *nfs_retval = -EIO; |
3128 | return false; | ||
3129 | } | ||
3130 | |||
3131 | static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) | ||
3132 | { | ||
3133 | int retval; | ||
3134 | |||
3135 | __decode_op_hdr(xdr, expected, &retval); | ||
3136 | return retval; | ||
3123 | } | 3137 | } |
3124 | 3138 | ||
3125 | /* Dummy routine */ | 3139 | /* Dummy routine */ |
@@ -3435,7 +3449,7 @@ static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint | |||
3435 | { | 3449 | { |
3436 | __be32 *p; | 3450 | __be32 *p; |
3437 | 3451 | ||
3438 | *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL; | 3452 | *res = 0; |
3439 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) | 3453 | if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U))) |
3440 | return -EIO; | 3454 | return -EIO; |
3441 | if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { | 3455 | if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) { |
@@ -5001,11 +5015,12 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | |||
5001 | uint32_t savewords, bmlen, i; | 5015 | uint32_t savewords, bmlen, i; |
5002 | int status; | 5016 | int status; |
5003 | 5017 | ||
5004 | status = decode_op_hdr(xdr, OP_OPEN); | 5018 | if (!__decode_op_hdr(xdr, OP_OPEN, &status)) |
5005 | if (status != -EIO) | 5019 | return status; |
5006 | nfs_increment_open_seqid(status, res->seqid); | 5020 | nfs_increment_open_seqid(status, res->seqid); |
5007 | if (!status) | 5021 | if (status) |
5008 | status = decode_stateid(xdr, &res->stateid); | 5022 | return status; |
5023 | status = decode_stateid(xdr, &res->stateid); | ||
5009 | if (unlikely(status)) | 5024 | if (unlikely(status)) |
5010 | return status; | 5025 | return status; |
5011 | 5026 | ||
diff --git a/fs/nfs/nfstrace.h b/fs/nfs/nfstrace.h index 89fe741e58b1..59f838cdc009 100644 --- a/fs/nfs/nfstrace.h +++ b/fs/nfs/nfstrace.h | |||
@@ -36,6 +36,7 @@ | |||
36 | __print_flags(v, "|", \ | 36 | __print_flags(v, "|", \ |
37 | { 1 << NFS_INO_ADVISE_RDPLUS, "ADVISE_RDPLUS" }, \ | 37 | { 1 << NFS_INO_ADVISE_RDPLUS, "ADVISE_RDPLUS" }, \ |
38 | { 1 << NFS_INO_STALE, "STALE" }, \ | 38 | { 1 << NFS_INO_STALE, "STALE" }, \ |
39 | { 1 << NFS_INO_INVALIDATING, "INVALIDATING" }, \ | ||
39 | { 1 << NFS_INO_FLUSHING, "FLUSHING" }, \ | 40 | { 1 << NFS_INO_FLUSHING, "FLUSHING" }, \ |
40 | { 1 << NFS_INO_FSCACHE, "FSCACHE" }, \ | 41 | { 1 << NFS_INO_FSCACHE, "FSCACHE" }, \ |
41 | { 1 << NFS_INO_COMMIT, "COMMIT" }, \ | 42 | { 1 << NFS_INO_COMMIT, "COMMIT" }, \ |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index d75d938d36cb..4755858e37a0 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1790,6 +1790,15 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | |||
1790 | } | 1790 | } |
1791 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages); | 1791 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages); |
1792 | 1792 | ||
1793 | static void pnfs_clear_layoutcommitting(struct inode *inode) | ||
1794 | { | ||
1795 | unsigned long *bitlock = &NFS_I(inode)->flags; | ||
1796 | |||
1797 | clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock); | ||
1798 | smp_mb__after_clear_bit(); | ||
1799 | wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING); | ||
1800 | } | ||
1801 | |||
1793 | /* | 1802 | /* |
1794 | * There can be multiple RW segments. | 1803 | * There can be multiple RW segments. |
1795 | */ | 1804 | */ |
@@ -1807,7 +1816,6 @@ static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp) | |||
1807 | static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp) | 1816 | static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp) |
1808 | { | 1817 | { |
1809 | struct pnfs_layout_segment *lseg, *tmp; | 1818 | struct pnfs_layout_segment *lseg, *tmp; |
1810 | unsigned long *bitlock = &NFS_I(inode)->flags; | ||
1811 | 1819 | ||
1812 | /* Matched by references in pnfs_set_layoutcommit */ | 1820 | /* Matched by references in pnfs_set_layoutcommit */ |
1813 | list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) { | 1821 | list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) { |
@@ -1815,9 +1823,7 @@ static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *lis | |||
1815 | pnfs_put_lseg(lseg); | 1823 | pnfs_put_lseg(lseg); |
1816 | } | 1824 | } |
1817 | 1825 | ||
1818 | clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock); | 1826 | pnfs_clear_layoutcommitting(inode); |
1819 | smp_mb__after_clear_bit(); | ||
1820 | wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING); | ||
1821 | } | 1827 | } |
1822 | 1828 | ||
1823 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg) | 1829 | void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg) |
@@ -1881,43 +1887,37 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) | |||
1881 | struct nfs4_layoutcommit_data *data; | 1887 | struct nfs4_layoutcommit_data *data; |
1882 | struct nfs_inode *nfsi = NFS_I(inode); | 1888 | struct nfs_inode *nfsi = NFS_I(inode); |
1883 | loff_t end_pos; | 1889 | loff_t end_pos; |
1884 | int status = 0; | 1890 | int status; |
1885 | 1891 | ||
1886 | dprintk("--> %s inode %lu\n", __func__, inode->i_ino); | 1892 | if (!pnfs_layoutcommit_outstanding(inode)) |
1887 | |||
1888 | if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) | ||
1889 | return 0; | 1893 | return 0; |
1890 | 1894 | ||
1891 | /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ | 1895 | dprintk("--> %s inode %lu\n", __func__, inode->i_ino); |
1892 | data = kzalloc(sizeof(*data), GFP_NOFS); | ||
1893 | if (!data) { | ||
1894 | status = -ENOMEM; | ||
1895 | goto out; | ||
1896 | } | ||
1897 | |||
1898 | if (!test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) | ||
1899 | goto out_free; | ||
1900 | 1896 | ||
1897 | status = -EAGAIN; | ||
1901 | if (test_and_set_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags)) { | 1898 | if (test_and_set_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags)) { |
1902 | if (!sync) { | 1899 | if (!sync) |
1903 | status = -EAGAIN; | 1900 | goto out; |
1904 | goto out_free; | 1901 | status = wait_on_bit_lock(&nfsi->flags, |
1905 | } | 1902 | NFS_INO_LAYOUTCOMMITTING, |
1906 | status = wait_on_bit_lock(&nfsi->flags, NFS_INO_LAYOUTCOMMITTING, | 1903 | nfs_wait_bit_killable, |
1907 | nfs_wait_bit_killable, TASK_KILLABLE); | 1904 | TASK_KILLABLE); |
1908 | if (status) | 1905 | if (status) |
1909 | goto out_free; | 1906 | goto out; |
1910 | } | 1907 | } |
1911 | 1908 | ||
1912 | INIT_LIST_HEAD(&data->lseg_list); | 1909 | status = -ENOMEM; |
1910 | /* Note kzalloc ensures data->res.seq_res.sr_slot == NULL */ | ||
1911 | data = kzalloc(sizeof(*data), GFP_NOFS); | ||
1912 | if (!data) | ||
1913 | goto clear_layoutcommitting; | ||
1914 | |||
1915 | status = 0; | ||
1913 | spin_lock(&inode->i_lock); | 1916 | spin_lock(&inode->i_lock); |
1914 | if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | 1917 | if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) |
1915 | clear_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags); | 1918 | goto out_unlock; |
1916 | spin_unlock(&inode->i_lock); | ||
1917 | wake_up_bit(&nfsi->flags, NFS_INO_LAYOUTCOMMITTING); | ||
1918 | goto out_free; | ||
1919 | } | ||
1920 | 1919 | ||
1920 | INIT_LIST_HEAD(&data->lseg_list); | ||
1921 | pnfs_list_write_lseg(inode, &data->lseg_list); | 1921 | pnfs_list_write_lseg(inode, &data->lseg_list); |
1922 | 1922 | ||
1923 | end_pos = nfsi->layout->plh_lwb; | 1923 | end_pos = nfsi->layout->plh_lwb; |
@@ -1940,8 +1940,11 @@ out: | |||
1940 | mark_inode_dirty_sync(inode); | 1940 | mark_inode_dirty_sync(inode); |
1941 | dprintk("<-- %s status %d\n", __func__, status); | 1941 | dprintk("<-- %s status %d\n", __func__, status); |
1942 | return status; | 1942 | return status; |
1943 | out_free: | 1943 | out_unlock: |
1944 | spin_unlock(&inode->i_lock); | ||
1944 | kfree(data); | 1945 | kfree(data); |
1946 | clear_layoutcommitting: | ||
1947 | pnfs_clear_layoutcommitting(inode); | ||
1945 | goto out; | 1948 | goto out; |
1946 | } | 1949 | } |
1947 | 1950 | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index a4f41810a7f4..023793909778 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -359,6 +359,15 @@ pnfs_ld_layoutret_on_setattr(struct inode *inode) | |||
359 | PNFS_LAYOUTRET_ON_SETATTR; | 359 | PNFS_LAYOUTRET_ON_SETATTR; |
360 | } | 360 | } |
361 | 361 | ||
362 | static inline bool | ||
363 | pnfs_layoutcommit_outstanding(struct inode *inode) | ||
364 | { | ||
365 | struct nfs_inode *nfsi = NFS_I(inode); | ||
366 | |||
367 | return test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags) != 0 || | ||
368 | test_bit(NFS_INO_LAYOUTCOMMITTING, &nfsi->flags) != 0; | ||
369 | } | ||
370 | |||
362 | static inline int pnfs_return_layout(struct inode *ino) | 371 | static inline int pnfs_return_layout(struct inode *ino) |
363 | { | 372 | { |
364 | struct nfs_inode *nfsi = NFS_I(ino); | 373 | struct nfs_inode *nfsi = NFS_I(ino); |
@@ -515,6 +524,13 @@ pnfs_use_threshold(struct nfs4_threshold **dst, struct nfs4_threshold *src, | |||
515 | return false; | 524 | return false; |
516 | } | 525 | } |
517 | 526 | ||
527 | static inline bool | ||
528 | pnfs_layoutcommit_outstanding(struct inode *inode) | ||
529 | { | ||
530 | return false; | ||
531 | } | ||
532 | |||
533 | |||
518 | static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) | 534 | static inline struct nfs4_threshold *pnfs_mdsthreshold_alloc(void) |
519 | { | 535 | { |
520 | return NULL; | 536 | return NULL; |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 31db5c366b81..411aedda14bb 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -163,9 +163,9 @@ static void nfs_readpage_release(struct nfs_page *req) | |||
163 | 163 | ||
164 | unlock_page(req->wb_page); | 164 | unlock_page(req->wb_page); |
165 | 165 | ||
166 | dprintk("NFS: read done (%s/%Ld %d@%Ld)\n", | 166 | dprintk("NFS: read done (%s/%Lu %d@%Ld)\n", |
167 | req->wb_context->dentry->d_inode->i_sb->s_id, | 167 | req->wb_context->dentry->d_inode->i_sb->s_id, |
168 | (long long)NFS_FILEID(req->wb_context->dentry->d_inode), | 168 | (unsigned long long)NFS_FILEID(req->wb_context->dentry->d_inode), |
169 | req->wb_bytes, | 169 | req->wb_bytes, |
170 | (long long)req_offset(req)); | 170 | (long long)req_offset(req)); |
171 | nfs_release_request(req); | 171 | nfs_release_request(req); |
@@ -228,11 +228,11 @@ int nfs_initiate_read(struct rpc_clnt *clnt, | |||
228 | /* Set up the initial task struct. */ | 228 | /* Set up the initial task struct. */ |
229 | NFS_PROTO(inode)->read_setup(data, &msg); | 229 | NFS_PROTO(inode)->read_setup(data, &msg); |
230 | 230 | ||
231 | dprintk("NFS: %5u initiated read call (req %s/%lld, %u bytes @ " | 231 | dprintk("NFS: %5u initiated read call (req %s/%llu, %u bytes @ " |
232 | "offset %llu)\n", | 232 | "offset %llu)\n", |
233 | data->task.tk_pid, | 233 | data->task.tk_pid, |
234 | inode->i_sb->s_id, | 234 | inode->i_sb->s_id, |
235 | (long long)NFS_FILEID(inode), | 235 | (unsigned long long)NFS_FILEID(inode), |
236 | data->args.count, | 236 | data->args.count, |
237 | (unsigned long long)data->args.offset); | 237 | (unsigned long long)data->args.offset); |
238 | 238 | ||
@@ -630,9 +630,9 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
630 | unsigned long npages; | 630 | unsigned long npages; |
631 | int ret = -ESTALE; | 631 | int ret = -ESTALE; |
632 | 632 | ||
633 | dprintk("NFS: nfs_readpages (%s/%Ld %d)\n", | 633 | dprintk("NFS: nfs_readpages (%s/%Lu %d)\n", |
634 | inode->i_sb->s_id, | 634 | inode->i_sb->s_id, |
635 | (long long)NFS_FILEID(inode), | 635 | (unsigned long long)NFS_FILEID(inode), |
636 | nr_pages); | 636 | nr_pages); |
637 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGES); | 637 | nfs_inc_stats(inode, NFSIOS_VFSREADPAGES); |
638 | 638 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index c1d548211c31..9a3b6a4cd6b9 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -909,9 +909,14 @@ bool nfs_ctx_key_to_expire(struct nfs_open_context *ctx) | |||
909 | */ | 909 | */ |
910 | static bool nfs_write_pageuptodate(struct page *page, struct inode *inode) | 910 | static bool nfs_write_pageuptodate(struct page *page, struct inode *inode) |
911 | { | 911 | { |
912 | struct nfs_inode *nfsi = NFS_I(inode); | ||
913 | |||
912 | if (nfs_have_delegated_attributes(inode)) | 914 | if (nfs_have_delegated_attributes(inode)) |
913 | goto out; | 915 | goto out; |
914 | if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE)) | 916 | if (nfsi->cache_validity & (NFS_INO_INVALID_DATA|NFS_INO_REVAL_PAGECACHE)) |
917 | return false; | ||
918 | smp_rmb(); | ||
919 | if (test_bit(NFS_INO_INVALIDATING, &nfsi->flags)) | ||
915 | return false; | 920 | return false; |
916 | out: | 921 | out: |
917 | return PageUptodate(page) != 0; | 922 | return PageUptodate(page) != 0; |
@@ -922,19 +927,20 @@ out: | |||
922 | * extend the write to cover the entire page in order to avoid fragmentation | 927 | * extend the write to cover the entire page in order to avoid fragmentation |
923 | * inefficiencies. | 928 | * inefficiencies. |
924 | * | 929 | * |
925 | * If the file is opened for synchronous writes or if we have a write delegation | 930 | * If the file is opened for synchronous writes then we can just skip the rest |
926 | * from the server then we can just skip the rest of the checks. | 931 | * of the checks. |
927 | */ | 932 | */ |
928 | static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode) | 933 | static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode) |
929 | { | 934 | { |
930 | if (file->f_flags & O_DSYNC) | 935 | if (file->f_flags & O_DSYNC) |
931 | return 0; | 936 | return 0; |
937 | if (!nfs_write_pageuptodate(page, inode)) | ||
938 | return 0; | ||
932 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) | 939 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) |
933 | return 1; | 940 | return 1; |
934 | if (nfs_write_pageuptodate(page, inode) && (inode->i_flock == NULL || | 941 | if (inode->i_flock == NULL || (inode->i_flock->fl_start == 0 && |
935 | (inode->i_flock->fl_start == 0 && | ||
936 | inode->i_flock->fl_end == OFFSET_MAX && | 942 | inode->i_flock->fl_end == OFFSET_MAX && |
937 | inode->i_flock->fl_type != F_RDLCK))) | 943 | inode->i_flock->fl_type != F_RDLCK)) |
938 | return 1; | 944 | return 1; |
939 | return 0; | 945 | return 0; |
940 | } | 946 | } |
@@ -1013,10 +1019,10 @@ int nfs_initiate_write(struct rpc_clnt *clnt, | |||
1013 | NFS_PROTO(inode)->write_setup(data, &msg); | 1019 | NFS_PROTO(inode)->write_setup(data, &msg); |
1014 | 1020 | ||
1015 | dprintk("NFS: %5u initiated write call " | 1021 | dprintk("NFS: %5u initiated write call " |
1016 | "(req %s/%lld, %u bytes @ offset %llu)\n", | 1022 | "(req %s/%llu, %u bytes @ offset %llu)\n", |
1017 | data->task.tk_pid, | 1023 | data->task.tk_pid, |
1018 | inode->i_sb->s_id, | 1024 | inode->i_sb->s_id, |
1019 | (long long)NFS_FILEID(inode), | 1025 | (unsigned long long)NFS_FILEID(inode), |
1020 | data->args.count, | 1026 | data->args.count, |
1021 | (unsigned long long)data->args.offset); | 1027 | (unsigned long long)data->args.offset); |
1022 | 1028 | ||
@@ -1606,9 +1612,9 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data) | |||
1606 | nfs_list_remove_request(req); | 1612 | nfs_list_remove_request(req); |
1607 | nfs_clear_page_commit(req->wb_page); | 1613 | nfs_clear_page_commit(req->wb_page); |
1608 | 1614 | ||
1609 | dprintk("NFS: commit (%s/%lld %d@%lld)", | 1615 | dprintk("NFS: commit (%s/%llu %d@%lld)", |
1610 | req->wb_context->dentry->d_sb->s_id, | 1616 | req->wb_context->dentry->d_sb->s_id, |
1611 | (long long)NFS_FILEID(req->wb_context->dentry->d_inode), | 1617 | (unsigned long long)NFS_FILEID(req->wb_context->dentry->d_inode), |
1612 | req->wb_bytes, | 1618 | req->wb_bytes, |
1613 | (long long)req_offset(req)); | 1619 | (long long)req_offset(req)); |
1614 | if (status < 0) { | 1620 | if (status < 0) { |