|
@@ -1429,6 +1429,7 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
|
|
}
|
|
}
|
|
|
|
|
|
open_flags = nd->intent.open.flags;
|
|
open_flags = nd->intent.open.flags;
|
|
|
|
+ attr.ia_valid = 0;
|
|
|
|
|
|
ctx = create_nfs_open_context(dentry, open_flags);
|
|
ctx = create_nfs_open_context(dentry, open_flags);
|
|
res = ERR_CAST(ctx);
|
|
res = ERR_CAST(ctx);
|
|
@@ -1437,11 +1438,14 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
|
|
|
|
|
|
if (nd->flags & LOOKUP_CREATE) {
|
|
if (nd->flags & LOOKUP_CREATE) {
|
|
attr.ia_mode = nd->intent.open.create_mode;
|
|
attr.ia_mode = nd->intent.open.create_mode;
|
|
- attr.ia_valid = ATTR_MODE;
|
|
|
|
|
|
+ attr.ia_valid |= ATTR_MODE;
|
|
attr.ia_mode &= ~current_umask();
|
|
attr.ia_mode &= ~current_umask();
|
|
- } else {
|
|
|
|
|
|
+ } else
|
|
open_flags &= ~(O_EXCL | O_CREAT);
|
|
open_flags &= ~(O_EXCL | O_CREAT);
|
|
- attr.ia_valid = 0;
|
|
|
|
|
|
+
|
|
|
|
+ if (open_flags & O_TRUNC) {
|
|
|
|
+ attr.ia_valid |= ATTR_SIZE;
|
|
|
|
+ attr.ia_size = 0;
|
|
}
|
|
}
|
|
|
|
|
|
/* Open the file on the server */
|
|
/* Open the file on the server */
|
|
@@ -1495,6 +1499,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
|
|
struct inode *inode;
|
|
struct inode *inode;
|
|
struct inode *dir;
|
|
struct inode *dir;
|
|
struct nfs_open_context *ctx;
|
|
struct nfs_open_context *ctx;
|
|
|
|
+ struct iattr attr;
|
|
int openflags, ret = 0;
|
|
int openflags, ret = 0;
|
|
|
|
|
|
if (nd->flags & LOOKUP_RCU)
|
|
if (nd->flags & LOOKUP_RCU)
|
|
@@ -1523,19 +1528,27 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
|
|
/* We cannot do exclusive creation on a positive dentry */
|
|
/* We cannot do exclusive creation on a positive dentry */
|
|
if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
|
|
if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
|
|
goto no_open_dput;
|
|
goto no_open_dput;
|
|
- /* We can't create new files, or truncate existing ones here */
|
|
|
|
- openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
|
|
|
|
|
|
+ /* We can't create new files here */
|
|
|
|
+ openflags &= ~(O_CREAT|O_EXCL);
|
|
|
|
|
|
ctx = create_nfs_open_context(dentry, openflags);
|
|
ctx = create_nfs_open_context(dentry, openflags);
|
|
ret = PTR_ERR(ctx);
|
|
ret = PTR_ERR(ctx);
|
|
if (IS_ERR(ctx))
|
|
if (IS_ERR(ctx))
|
|
goto out;
|
|
goto out;
|
|
|
|
+
|
|
|
|
+ attr.ia_valid = 0;
|
|
|
|
+ if (openflags & O_TRUNC) {
|
|
|
|
+ attr.ia_valid |= ATTR_SIZE;
|
|
|
|
+ attr.ia_size = 0;
|
|
|
|
+ nfs_wb_all(inode);
|
|
|
|
+ }
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Note: we're not holding inode->i_mutex and so may be racing with
|
|
* Note: we're not holding inode->i_mutex and so may be racing with
|
|
* operations that change the directory. We therefore save the
|
|
* operations that change the directory. We therefore save the
|
|
* change attribute *before* we do the RPC call.
|
|
* change attribute *before* we do the RPC call.
|
|
*/
|
|
*/
|
|
- inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL);
|
|
|
|
|
|
+ inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
|
|
if (IS_ERR(inode)) {
|
|
if (IS_ERR(inode)) {
|
|
ret = PTR_ERR(inode);
|
|
ret = PTR_ERR(inode);
|
|
switch (ret) {
|
|
switch (ret) {
|