mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
smb: client: set ATTR_TEMPORARY with O_TMPFILE | O_EXCL
Set ATTR_TEMPORARY attribute on temporary delete-on-close files when O_EXCL is specified in conjunction with O_TMPFILE to let some servers cache as much data as possible and possibly never persist them into storage, thereby improving performance. Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Cc: David Howells <dhowells@redhat.com> Cc: linux-cifs@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
3e7d63037a
commit
62e02084ab
|
|
@ -1014,28 +1014,21 @@ static int cifs_ci_compare(const struct dentry *dentry,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int set_hidden_attr(const unsigned int xid,
|
||||
struct TCP_Server_Info *server,
|
||||
struct file *file)
|
||||
static int set_tmpfile_attr(const unsigned int xid, unsigned int oflags,
|
||||
struct inode *inode, const char *full_path,
|
||||
struct TCP_Server_Info *server)
|
||||
{
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry));
|
||||
FILE_BASIC_INFO fi = {
|
||||
.Attributes = cpu_to_le32(cinode->cifsAttrs |
|
||||
ATTR_HIDDEN),
|
||||
};
|
||||
void *page = alloc_dentry_path();
|
||||
const char *full_path;
|
||||
int rc;
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
FILE_BASIC_INFO fi;
|
||||
|
||||
full_path = build_path_from_dentry(dentry, page);
|
||||
if (IS_ERR(full_path))
|
||||
rc = PTR_ERR(full_path);
|
||||
else
|
||||
rc = server->ops->set_file_info(d_inode(dentry),
|
||||
full_path, &fi, xid);
|
||||
free_dentry_path(page);
|
||||
return rc;
|
||||
cinode->cifsAttrs |= ATTR_HIDDEN;
|
||||
if (oflags & O_EXCL)
|
||||
cinode->cifsAttrs |= ATTR_TEMPORARY;
|
||||
|
||||
fi = (FILE_BASIC_INFO) {
|
||||
.Attributes = cpu_to_le32(cinode->cifsAttrs),
|
||||
};
|
||||
return server->ops->set_file_info(inode, full_path, &fi, xid);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1049,6 +1042,8 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
|
|||
{
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct cifs_sb_info *cifs_sb = CIFS_SB(dir);
|
||||
char *path __free(kfree) = NULL, *name;
|
||||
unsigned int oflags = file->f_flags;
|
||||
size_t size = CIFS_TMPNAME_LEN + 1;
|
||||
int retries = 0, max_retries = 16;
|
||||
struct TCP_Server_Info *server;
|
||||
|
|
@ -1059,7 +1054,6 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
|
|||
struct cifs_tcon *tcon;
|
||||
unsigned int sbflags;
|
||||
struct inode *inode;
|
||||
char *path, *name;
|
||||
unsigned int xid;
|
||||
__u32 oplock;
|
||||
int rc;
|
||||
|
|
@ -1089,6 +1083,7 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
|
|||
if (IS_ERR(path)) {
|
||||
cifs_del_pending_open(&open);
|
||||
rc = PTR_ERR(path);
|
||||
path = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1098,9 +1093,8 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
|
|||
CIFS_TMPNAME_PREFIX "%0*x",
|
||||
CIFS_TMPNAME_COUNTER_LEN,
|
||||
atomic_inc_return(&cifs_tmpcounter));
|
||||
rc = __cifs_do_create(dir, dentry, path, xid, tlink,
|
||||
file->f_flags, mode, &oplock,
|
||||
&fid, NULL, &inode);
|
||||
rc = __cifs_do_create(dir, dentry, path, xid, tlink, oflags,
|
||||
mode, &oplock, &fid, NULL, &inode);
|
||||
if (!rc) {
|
||||
set_nlink(inode, 0);
|
||||
mark_inode_dirty(inode);
|
||||
|
|
@ -1110,7 +1104,6 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
|
|||
}
|
||||
} while (unlikely(rc == -EEXIST) && ++retries < max_retries);
|
||||
|
||||
kfree(path);
|
||||
if (rc) {
|
||||
cifs_del_pending_open(&open);
|
||||
goto out;
|
||||
|
|
@ -1134,7 +1127,7 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
|
|||
goto err_open;
|
||||
}
|
||||
|
||||
rc = set_hidden_attr(xid, server, file);
|
||||
rc = set_tmpfile_attr(xid, oflags, inode, path, server);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
|
|
|
|||
|
|
@ -1237,6 +1237,20 @@ int smb2_rename_path(const unsigned int xid,
|
|||
return rc;
|
||||
}
|
||||
|
||||
static int clear_tmpfile_attr(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct inode *inode, const char *full_path)
|
||||
{
|
||||
struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
FILE_BASIC_INFO fi;
|
||||
|
||||
cinode->cifsAttrs &= ~(ATTR_TEMPORARY | ATTR_HIDDEN);
|
||||
fi = (FILE_BASIC_INFO) {
|
||||
.Attributes = cpu_to_le32(cinode->cifsAttrs),
|
||||
};
|
||||
return server->ops->set_file_info(inode, full_path, &fi, xid);
|
||||
}
|
||||
|
||||
int smb2_create_hardlink(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
struct dentry *source_dentry,
|
||||
|
|
@ -1246,24 +1260,14 @@ int smb2_create_hardlink(const unsigned int xid,
|
|||
struct inode *inode = source_dentry ? d_inode(source_dentry) : NULL;
|
||||
__u32 co = file_create_options(source_dentry);
|
||||
struct cifsFileInfo *cfile;
|
||||
int rc;
|
||||
|
||||
if (inode) {
|
||||
struct cifsInodeInfo *cinode = CIFS_I(inode);
|
||||
FILE_BASIC_INFO fi;
|
||||
__le32 attrs;
|
||||
int rc;
|
||||
|
||||
if (!test_bit(CIFS_INO_TMPFILE, &CIFS_I(inode)->flags))
|
||||
goto out;
|
||||
|
||||
attrs = cpu_to_le32(cinode->cifsAttrs & ~ATTR_HIDDEN);
|
||||
fi = (FILE_BASIC_INFO){ .Attributes = attrs, };
|
||||
rc = smb2_set_file_info(inode, from_name, &fi, xid);
|
||||
if (inode && test_bit(CIFS_INO_TMPFILE, &CIFS_I(inode)->flags)) {
|
||||
rc = clear_tmpfile_attr(xid, tcon, inode, from_name);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
out:
|
||||
cifs_get_writable_path(tcon, from_name, inode,
|
||||
FIND_WITH_DELETE, &cfile);
|
||||
return smb2_set_path_attr(xid, tcon, from_name, to_name,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user