Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6

* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
nfs: fix memory leak in nfs_get_sb with CONFIG_NFS_V4
nfs: fix some issues in nfs41_proc_reclaim_complete()
NFS: Ensure that nfs_wb_page() waits for Pg_writeback to clear
NFS: Fix an unstable write data integrity race
nfs: testing for null instead of ERR_PTR()
NFS: rsize and wsize settings ignored on v4 mounts
NFSv4: Don't attempt an atomic open if the file is a mountpoint
SUNRPC: Fix a bug in rpcauth_prune_expired

+47 -23
+2
fs/nfs/client.c
··· 966 966 static void nfs_server_copy_userdata(struct nfs_server *target, struct nfs_server *source) 967 967 { 968 968 target->flags = source->flags; 969 + target->rsize = source->rsize; 970 + target->wsize = source->wsize; 969 971 target->acregmin = source->acregmin; 970 972 target->acregmax = source->acregmax; 971 973 target->acdirmin = source->acdirmin;
+1 -1
fs/nfs/dir.c
··· 1052 1052 struct inode *dir; 1053 1053 int openflags, ret = 0; 1054 1054 1055 - if (!is_atomic_open(nd)) 1055 + if (!is_atomic_open(nd) || d_mountpoint(dentry)) 1056 1056 goto no_open; 1057 1057 parent = dget_parent(dentry); 1058 1058 dir = parent->d_inode;
+4 -1
fs/nfs/nfs4proc.c
··· 5218 5218 msg.rpc_resp = &calldata->res; 5219 5219 task_setup_data.callback_data = calldata; 5220 5220 task = rpc_run_task(&task_setup_data); 5221 - if (IS_ERR(task)) 5221 + if (IS_ERR(task)) { 5222 5222 status = PTR_ERR(task); 5223 + goto out; 5224 + } 5223 5225 rpc_put_task(task); 5226 + return 0; 5224 5227 out: 5225 5228 dprintk("<-- %s status=%d\n", __func__, status); 5226 5229 return status;
+2 -1
fs/nfs/super.c
··· 2187 2187 if (data->version == 4) { 2188 2188 error = nfs4_try_mount(flags, dev_name, data, mnt); 2189 2189 kfree(data->client_address); 2190 + kfree(data->nfs_server.export_path); 2190 2191 goto out; 2191 2192 } 2192 2193 #endif /* CONFIG_NFS_V4 */ ··· 2658 2657 devname = nfs_path(path->mnt->mnt_devname, 2659 2658 path->mnt->mnt_root, path->dentry, 2660 2659 page, PAGE_SIZE); 2661 - if (devname == NULL) 2660 + if (IS_ERR(devname)) 2662 2661 goto out_freepage; 2663 2662 tmp = kstrdup(devname, GFP_KERNEL); 2664 2663 if (tmp == NULL)
+36 -19
fs/nfs/write.c
··· 1201 1201 1202 1202 1203 1203 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) 1204 + static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) 1205 + { 1206 + if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) 1207 + return 1; 1208 + if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags, 1209 + NFS_INO_COMMIT, nfs_wait_bit_killable, 1210 + TASK_KILLABLE)) 1211 + return 1; 1212 + return 0; 1213 + } 1214 + 1215 + static void nfs_commit_clear_lock(struct nfs_inode *nfsi) 1216 + { 1217 + clear_bit(NFS_INO_COMMIT, &nfsi->flags); 1218 + smp_mb__after_clear_bit(); 1219 + wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); 1220 + } 1221 + 1222 + 1204 1223 static void nfs_commitdata_release(void *data) 1205 1224 { 1206 1225 struct nfs_write_data *wdata = data; ··· 1281 1262 task = rpc_run_task(&task_setup_data); 1282 1263 if (IS_ERR(task)) 1283 1264 return PTR_ERR(task); 1284 - if (how & FLUSH_SYNC) 1285 - rpc_wait_for_completion_task(task); 1286 1265 rpc_put_task(task); 1287 1266 return 0; 1288 1267 } ··· 1311 1294 BDI_RECLAIMABLE); 1312 1295 nfs_clear_page_tag_locked(req); 1313 1296 } 1297 + nfs_commit_clear_lock(NFS_I(inode)); 1314 1298 return -ENOMEM; 1315 1299 } 1316 1300 ··· 1367 1349 next: 1368 1350 nfs_clear_page_tag_locked(req); 1369 1351 } 1352 + nfs_commit_clear_lock(NFS_I(data->inode)); 1370 1353 nfs_commitdata_release(calldata); 1371 1354 } 1372 1355 ··· 1382 1363 static int nfs_commit_inode(struct inode *inode, int how) 1383 1364 { 1384 1365 LIST_HEAD(head); 1385 - int res; 1366 + int may_wait = how & FLUSH_SYNC; 1367 + int res = 0; 1386 1368 1369 + if (!nfs_commit_set_lock(NFS_I(inode), may_wait)) 1370 + goto out; 1387 1371 spin_lock(&inode->i_lock); 1388 1372 res = nfs_scan_commit(inode, &head, 0, 0); 1389 1373 spin_unlock(&inode->i_lock); ··· 1394 1372 int error = nfs_commit_list(inode, &head, how); 1395 1373 if (error < 0) 1396 1374 return error; 1397 - } 1375 + if (may_wait) 1376 + wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT, 1377 + nfs_wait_bit_killable, 1378 + TASK_KILLABLE); 1379 + } else 1380 + nfs_commit_clear_lock(NFS_I(inode)); 1381 + out: 1398 1382 return res; 1399 1383 } 1400 1384 ··· 1472 1444 1473 1445 BUG_ON(!PageLocked(page)); 1474 1446 for (;;) { 1447 + wait_on_page_writeback(page); 1475 1448 req = nfs_page_find_request(page); 1476 1449 if (req == NULL) 1477 1450 break; ··· 1507 1478 .range_start = range_start, 1508 1479 .range_end = range_end, 1509 1480 }; 1510 - struct nfs_page *req; 1511 - int need_commit; 1512 1481 int ret; 1513 1482 1514 1483 while(PagePrivate(page)) { 1484 + wait_on_page_writeback(page); 1515 1485 if (clear_page_dirty_for_io(page)) { 1516 1486 ret = nfs_writepage_locked(page, &wbc); 1517 1487 if (ret < 0) 1518 1488 goto out_error; 1519 1489 } 1520 - req = nfs_find_and_lock_request(page); 1521 - if (!req) 1522 - break; 1523 - if (IS_ERR(req)) { 1524 - ret = PTR_ERR(req); 1490 + ret = sync_inode(inode, &wbc); 1491 + if (ret < 0) 1525 1492 goto out_error; 1526 - } 1527 - need_commit = test_bit(PG_CLEAN, &req->wb_flags); 1528 - nfs_clear_page_tag_locked(req); 1529 - if (need_commit) { 1530 - ret = nfs_commit_inode(inode, FLUSH_SYNC); 1531 - if (ret < 0) 1532 - goto out_error; 1533 - } 1534 1493 } 1535 1494 return 0; 1536 1495 out_error:
+1
include/linux/nfs_fs.h
··· 209 209 #define NFS_INO_FLUSHING (4) /* inode is flushing out data */ 210 210 #define NFS_INO_FSCACHE (5) /* inode can be cached by FS-Cache */ 211 211 #define NFS_INO_FSCACHE_LOCK (6) /* FS-Cache cookie management lock */ 212 + #define NFS_INO_COMMIT (7) /* inode is committing unstable writes */ 212 213 213 214 static inline struct nfs_inode *NFS_I(const struct inode *inode) 214 215 {
+1 -1
net/sunrpc/auth.c
··· 237 237 list_for_each_entry_safe(cred, next, &cred_unused, cr_lru) { 238 238 239 239 /* Enforce a 60 second garbage collection moratorium */ 240 - if (time_in_range_open(cred->cr_expire, expired, jiffies) && 240 + if (time_in_range(cred->cr_expire, expired, jiffies) && 241 241 test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) 242 242 continue; 243 243