@@ -111,11 +111,15 @@ const struct inode_operations nfs3_dir_inode_operations = {
111
111
112
112
#ifdef CONFIG_NFS_V4
113
113
114
- static struct dentry * nfs_atomic_lookup (struct inode * , struct dentry * , struct nameidata * );
115
- static int nfs_open_create (struct inode * dir , struct dentry * dentry , umode_t mode , struct nameidata * nd );
114
+ static struct file * nfs_atomic_open (struct inode * , struct dentry * ,
115
+ struct opendata * , unsigned , umode_t ,
116
+ bool * );
117
+ static int nfs4_create (struct inode * dir , struct dentry * dentry ,
118
+ umode_t mode , struct nameidata * nd );
116
119
const struct inode_operations nfs4_dir_inode_operations = {
117
- .create = nfs_open_create ,
118
- .lookup = nfs_atomic_lookup ,
120
+ .create = nfs4_create ,
121
+ .lookup = nfs_lookup ,
122
+ .atomic_open = nfs_atomic_open ,
119
123
.link = nfs_link ,
120
124
.unlink = nfs_unlink ,
121
125
.symlink = nfs_symlink ,
@@ -1403,120 +1407,132 @@ static int do_open(struct inode *inode, struct file *filp)
1403
1407
return 0 ;
1404
1408
}
1405
1409
1406
- static int nfs_intent_set_file (struct nameidata * nd , struct nfs_open_context * ctx )
1410
+ static struct file * nfs_finish_open (struct nfs_open_context * ctx ,
1411
+ struct dentry * dentry ,
1412
+ struct opendata * od , unsigned open_flags )
1407
1413
{
1408
1414
struct file * filp ;
1409
- int ret = 0 ;
1415
+ int err ;
1416
+
1417
+ if (ctx -> dentry != dentry ) {
1418
+ dput (ctx -> dentry );
1419
+ ctx -> dentry = dget (dentry );
1420
+ }
1410
1421
1411
1422
/* If the open_intent is for execute, we have an extra check to make */
1412
1423
if (ctx -> mode & FMODE_EXEC ) {
1413
- ret = nfs_may_open (ctx -> dentry -> d_inode ,
1414
- ctx -> cred ,
1415
- nd -> intent .open .flags );
1416
- if (ret < 0 )
1424
+ err = nfs_may_open (dentry -> d_inode , ctx -> cred , open_flags );
1425
+ if (err < 0 ) {
1426
+ filp = ERR_PTR (err );
1417
1427
goto out ;
1428
+ }
1418
1429
}
1419
- filp = lookup_instantiate_filp (nd , ctx -> dentry , do_open );
1420
- if (IS_ERR (filp ))
1421
- ret = PTR_ERR (filp );
1422
- else
1430
+
1431
+ filp = finish_open (od , dentry , do_open );
1432
+ if (!IS_ERR (filp ))
1423
1433
nfs_file_set_open_context (filp , ctx );
1434
+
1424
1435
out :
1425
1436
put_nfs_open_context (ctx );
1426
- return ret ;
1437
+ return filp ;
1427
1438
}
1428
1439
1429
- static struct dentry * nfs_atomic_lookup (struct inode * dir , struct dentry * dentry , struct nameidata * nd )
1440
+ static struct file * nfs_atomic_open (struct inode * dir , struct dentry * dentry ,
1441
+ struct opendata * od , unsigned open_flags ,
1442
+ umode_t mode , bool * created )
1430
1443
{
1431
1444
struct nfs_open_context * ctx ;
1432
- struct iattr attr ;
1433
- struct dentry * res = NULL ;
1445
+ struct dentry * res ;
1446
+ struct iattr attr = { . ia_valid = ATTR_OPEN } ;
1434
1447
struct inode * inode ;
1435
- int open_flags ;
1448
+ struct file * filp ;
1436
1449
int err ;
1437
1450
1438
- dfprintk (VFS , "NFS: atomic_lookup(%s/%ld), %s\n" ,
1451
+ /* Expect a negative dentry */
1452
+ BUG_ON (dentry -> d_inode );
1453
+
1454
+ dfprintk (VFS , "NFS: atomic_open(%s/%ld), %s\n" ,
1439
1455
dir -> i_sb -> s_id , dir -> i_ino , dentry -> d_name .name );
1440
1456
1441
- /* Check that we are indeed trying to open this file */
1442
- if (!is_atomic_open (nd ))
1457
+ /* NFS only supports OPEN on regular files */
1458
+ if ((open_flags & O_DIRECTORY )) {
1459
+ err = - ENOENT ;
1460
+ if (!d_unhashed (dentry )) {
1461
+ /*
1462
+ * Hashed negative dentry with O_DIRECTORY: dentry was
1463
+ * revalidated and is fine, no need to perform lookup
1464
+ * again
1465
+ */
1466
+ goto out_err ;
1467
+ }
1443
1468
goto no_open ;
1444
-
1445
- if (dentry -> d_name .len > NFS_SERVER (dir )-> namelen ) {
1446
- res = ERR_PTR (- ENAMETOOLONG );
1447
- goto out ;
1448
1469
}
1449
1470
1450
- /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash
1451
- * the dentry. */
1452
- if (nd -> flags & LOOKUP_EXCL ) {
1453
- d_instantiate (dentry , NULL );
1454
- goto out ;
1455
- }
1456
-
1457
- open_flags = nd -> intent .open .flags ;
1458
- attr .ia_valid = ATTR_OPEN ;
1459
-
1460
- ctx = create_nfs_open_context (dentry , open_flags );
1461
- res = ERR_CAST (ctx );
1462
- if (IS_ERR (ctx ))
1463
- goto out ;
1471
+ err = - ENAMETOOLONG ;
1472
+ if (dentry -> d_name .len > NFS_SERVER (dir )-> namelen )
1473
+ goto out_err ;
1464
1474
1465
- if (nd -> flags & LOOKUP_CREATE ) {
1466
- attr .ia_mode = nd -> intent .open .create_mode ;
1475
+ if (open_flags & O_CREAT ) {
1467
1476
attr .ia_valid |= ATTR_MODE ;
1468
- attr .ia_mode &= ~current_umask ();
1469
- } else
1470
- open_flags &= ~(O_EXCL | O_CREAT );
1471
-
1477
+ attr .ia_mode = mode & ~current_umask ();
1478
+ }
1472
1479
if (open_flags & O_TRUNC ) {
1473
1480
attr .ia_valid |= ATTR_SIZE ;
1474
1481
attr .ia_size = 0 ;
1475
1482
}
1476
1483
1477
- /* Open the file on the server */
1484
+ ctx = create_nfs_open_context (dentry , open_flags );
1485
+ err = PTR_ERR (ctx );
1486
+ if (IS_ERR (ctx ))
1487
+ goto out_err ;
1488
+
1478
1489
nfs_block_sillyrename (dentry -> d_parent );
1479
1490
inode = NFS_PROTO (dir )-> open_context (dir , ctx , open_flags , & attr );
1491
+ d_drop (dentry );
1480
1492
if (IS_ERR (inode )) {
1481
1493
nfs_unblock_sillyrename (dentry -> d_parent );
1482
1494
put_nfs_open_context (ctx );
1483
- switch (PTR_ERR (inode )) {
1484
- /* Make a negative dentry */
1485
- case - ENOENT :
1486
- d_add (dentry , NULL );
1487
- res = NULL ;
1488
- goto out ;
1489
- /* This turned out not to be a regular file */
1490
- case - EISDIR :
1491
- case - ENOTDIR :
1495
+ err = PTR_ERR (inode );
1496
+ switch (err ) {
1497
+ case - ENOENT :
1498
+ d_add (dentry , NULL );
1499
+ break ;
1500
+ case - EISDIR :
1501
+ case - ENOTDIR :
1502
+ goto no_open ;
1503
+ case - ELOOP :
1504
+ if (!(open_flags & O_NOFOLLOW ))
1492
1505
goto no_open ;
1493
- case - ELOOP :
1494
- if (!(nd -> intent .open .flags & O_NOFOLLOW ))
1495
- goto no_open ;
1506
+ break ;
1496
1507
/* case -EINVAL: */
1497
- default :
1498
- res = ERR_CAST (inode );
1499
- goto out ;
1508
+ default :
1509
+ break ;
1500
1510
}
1511
+ goto out_err ;
1501
1512
}
1502
1513
res = d_add_unique (dentry , inode );
1503
- nfs_unblock_sillyrename (dentry -> d_parent );
1504
- if (res != NULL ) {
1505
- dput (ctx -> dentry );
1506
- ctx -> dentry = dget (res );
1514
+ if (res != NULL )
1507
1515
dentry = res ;
1508
- }
1509
- err = nfs_intent_set_file (nd , ctx );
1510
- if (err < 0 ) {
1511
- if (res != NULL )
1512
- dput (res );
1513
- return ERR_PTR (err );
1514
- }
1515
- out :
1516
+
1517
+ nfs_unblock_sillyrename (dentry -> d_parent );
1516
1518
nfs_set_verifier (dentry , nfs_save_change_attribute (dir ));
1517
- return res ;
1519
+
1520
+ filp = nfs_finish_open (ctx , dentry , od , open_flags );
1521
+
1522
+ dput (res );
1523
+ return filp ;
1524
+
1525
+ out_err :
1526
+ return ERR_PTR (err );
1527
+
1518
1528
no_open :
1519
- return nfs_lookup (dir , dentry , nd );
1529
+ res = nfs_lookup (dir , dentry , NULL );
1530
+ err = PTR_ERR (res );
1531
+ if (IS_ERR (res ))
1532
+ goto out_err ;
1533
+
1534
+ finish_no_open (od , res );
1535
+ return NULL ;
1520
1536
}
1521
1537
1522
1538
static int nfs4_lookup_revalidate (struct dentry * dentry , struct nameidata * nd )
@@ -1566,8 +1582,8 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
1566
1582
return nfs_lookup_revalidate (dentry , nd );
1567
1583
}
1568
1584
1569
- static int nfs_open_create (struct inode * dir , struct dentry * dentry ,
1570
- umode_t mode , struct nameidata * nd )
1585
+ static int nfs4_create (struct inode * dir , struct dentry * dentry ,
1586
+ umode_t mode , struct nameidata * nd )
1571
1587
{
1572
1588
struct nfs_open_context * ctx = NULL ;
1573
1589
struct iattr attr ;
@@ -1591,19 +1607,14 @@ static int nfs_open_create(struct inode *dir, struct dentry *dentry,
1591
1607
error = NFS_PROTO (dir )-> create (dir , dentry , & attr , open_flags , ctx );
1592
1608
if (error != 0 )
1593
1609
goto out_put_ctx ;
1594
- if (nd ) {
1595
- error = nfs_intent_set_file (nd , ctx );
1596
- if (error < 0 )
1597
- goto out_err ;
1598
- } else {
1599
- put_nfs_open_context (ctx );
1600
- }
1610
+
1611
+ put_nfs_open_context (ctx );
1612
+
1601
1613
return 0 ;
1602
1614
out_put_ctx :
1603
1615
put_nfs_open_context (ctx );
1604
1616
out_err_drop :
1605
1617
d_drop (dentry );
1606
- out_err :
1607
1618
return error ;
1608
1619
}
1609
1620
0 commit comments