@@ -111,11 +111,15 @@ const struct inode_operations nfs3_dir_inode_operations = {
111111
112112#ifdef CONFIG_NFS_V4
113113
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 );
116119const 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 ,
119123 .link = nfs_link ,
120124 .unlink = nfs_unlink ,
121125 .symlink = nfs_symlink ,
@@ -1403,120 +1407,132 @@ static int do_open(struct inode *inode, struct file *filp)
14031407 return 0 ;
14041408}
14051409
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 )
14071413{
14081414 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+ }
14101421
14111422 /* If the open_intent is for execute, we have an extra check to make */
14121423 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 );
14171427 goto out ;
1428+ }
14181429 }
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 ))
14231433 nfs_file_set_open_context (filp , ctx );
1434+
14241435out :
14251436 put_nfs_open_context (ctx );
1426- return ret ;
1437+ return filp ;
14271438}
14281439
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 )
14301443{
14311444 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 } ;
14341447 struct inode * inode ;
1435- int open_flags ;
1448+ struct file * filp ;
14361449 int err ;
14371450
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" ,
14391455 dir -> i_sb -> s_id , dir -> i_ino , dentry -> d_name .name );
14401456
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+ }
14431468 goto no_open ;
1444-
1445- if (dentry -> d_name .len > NFS_SERVER (dir )-> namelen ) {
1446- res = ERR_PTR (- ENAMETOOLONG );
1447- goto out ;
14481469 }
14491470
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 ;
14641474
1465- if (nd -> flags & LOOKUP_CREATE ) {
1466- attr .ia_mode = nd -> intent .open .create_mode ;
1475+ if (open_flags & O_CREAT ) {
14671476 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+ }
14721479 if (open_flags & O_TRUNC ) {
14731480 attr .ia_valid |= ATTR_SIZE ;
14741481 attr .ia_size = 0 ;
14751482 }
14761483
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+
14781489 nfs_block_sillyrename (dentry -> d_parent );
14791490 inode = NFS_PROTO (dir )-> open_context (dir , ctx , open_flags , & attr );
1491+ d_drop (dentry );
14801492 if (IS_ERR (inode )) {
14811493 nfs_unblock_sillyrename (dentry -> d_parent );
14821494 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 ))
14921505 goto no_open ;
1493- case - ELOOP :
1494- if (!(nd -> intent .open .flags & O_NOFOLLOW ))
1495- goto no_open ;
1506+ break ;
14961507 /* case -EINVAL: */
1497- default :
1498- res = ERR_CAST (inode );
1499- goto out ;
1508+ default :
1509+ break ;
15001510 }
1511+ goto out_err ;
15011512 }
15021513 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 )
15071515 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 );
15161518 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+
15181528no_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 ;
15201536}
15211537
15221538static 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)
15661582 return nfs_lookup_revalidate (dentry , nd );
15671583}
15681584
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 )
15711587{
15721588 struct nfs_open_context * ctx = NULL ;
15731589 struct iattr attr ;
@@ -1591,19 +1607,14 @@ static int nfs_open_create(struct inode *dir, struct dentry *dentry,
15911607 error = NFS_PROTO (dir )-> create (dir , dentry , & attr , open_flags , ctx );
15921608 if (error != 0 )
15931609 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+
16011613 return 0 ;
16021614out_put_ctx :
16031615 put_nfs_open_context (ctx );
16041616out_err_drop :
16051617 d_drop (dentry );
1606- out_err :
16071618 return error ;
16081619}
16091620
0 commit comments