Skip to content

Commit 62e0208

Browse files
pcacjrsmfrench
authored andcommitted
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>
1 parent 3e7d630 commit 62e0208

2 files changed

Lines changed: 36 additions & 39 deletions

File tree

fs/smb/client/dir.c

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,28 +1014,21 @@ static int cifs_ci_compare(const struct dentry *dentry,
10141014
return 0;
10151015
}
10161016

1017-
static int set_hidden_attr(const unsigned int xid,
1018-
struct TCP_Server_Info *server,
1019-
struct file *file)
1017+
static int set_tmpfile_attr(const unsigned int xid, unsigned int oflags,
1018+
struct inode *inode, const char *full_path,
1019+
struct TCP_Server_Info *server)
10201020
{
1021-
struct dentry *dentry = file->f_path.dentry;
1022-
struct cifsInodeInfo *cinode = CIFS_I(d_inode(dentry));
1023-
FILE_BASIC_INFO fi = {
1024-
.Attributes = cpu_to_le32(cinode->cifsAttrs |
1025-
ATTR_HIDDEN),
1026-
};
1027-
void *page = alloc_dentry_path();
1028-
const char *full_path;
1029-
int rc;
1021+
struct cifsInodeInfo *cinode = CIFS_I(inode);
1022+
FILE_BASIC_INFO fi;
10301023

1031-
full_path = build_path_from_dentry(dentry, page);
1032-
if (IS_ERR(full_path))
1033-
rc = PTR_ERR(full_path);
1034-
else
1035-
rc = server->ops->set_file_info(d_inode(dentry),
1036-
full_path, &fi, xid);
1037-
free_dentry_path(page);
1038-
return rc;
1024+
cinode->cifsAttrs |= ATTR_HIDDEN;
1025+
if (oflags & O_EXCL)
1026+
cinode->cifsAttrs |= ATTR_TEMPORARY;
1027+
1028+
fi = (FILE_BASIC_INFO) {
1029+
.Attributes = cpu_to_le32(cinode->cifsAttrs),
1030+
};
1031+
return server->ops->set_file_info(inode, full_path, &fi, xid);
10391032
}
10401033

10411034
/*
@@ -1049,6 +1042,8 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
10491042
{
10501043
struct dentry *dentry = file->f_path.dentry;
10511044
struct cifs_sb_info *cifs_sb = CIFS_SB(dir);
1045+
char *path __free(kfree) = NULL, *name;
1046+
unsigned int oflags = file->f_flags;
10521047
size_t size = CIFS_TMPNAME_LEN + 1;
10531048
int retries = 0, max_retries = 16;
10541049
struct TCP_Server_Info *server;
@@ -1059,7 +1054,6 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
10591054
struct cifs_tcon *tcon;
10601055
unsigned int sbflags;
10611056
struct inode *inode;
1062-
char *path, *name;
10631057
unsigned int xid;
10641058
__u32 oplock;
10651059
int rc;
@@ -1089,6 +1083,7 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
10891083
if (IS_ERR(path)) {
10901084
cifs_del_pending_open(&open);
10911085
rc = PTR_ERR(path);
1086+
path = NULL;
10921087
goto out;
10931088
}
10941089

@@ -1098,9 +1093,8 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
10981093
CIFS_TMPNAME_PREFIX "%0*x",
10991094
CIFS_TMPNAME_COUNTER_LEN,
11001095
atomic_inc_return(&cifs_tmpcounter));
1101-
rc = __cifs_do_create(dir, dentry, path, xid, tlink,
1102-
file->f_flags, mode, &oplock,
1103-
&fid, NULL, &inode);
1096+
rc = __cifs_do_create(dir, dentry, path, xid, tlink, oflags,
1097+
mode, &oplock, &fid, NULL, &inode);
11041098
if (!rc) {
11051099
set_nlink(inode, 0);
11061100
mark_inode_dirty(inode);
@@ -1110,7 +1104,6 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
11101104
}
11111105
} while (unlikely(rc == -EEXIST) && ++retries < max_retries);
11121106

1113-
kfree(path);
11141107
if (rc) {
11151108
cifs_del_pending_open(&open);
11161109
goto out;
@@ -1134,7 +1127,7 @@ int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
11341127
goto err_open;
11351128
}
11361129

1137-
rc = set_hidden_attr(xid, server, file);
1130+
rc = set_tmpfile_attr(xid, oflags, inode, path, server);
11381131
if (rc)
11391132
goto out;
11401133

fs/smb/client/smb2inode.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,20 @@ int smb2_rename_path(const unsigned int xid,
12371237
return rc;
12381238
}
12391239

1240+
static int clear_tmpfile_attr(const unsigned int xid, struct cifs_tcon *tcon,
1241+
struct inode *inode, const char *full_path)
1242+
{
1243+
struct TCP_Server_Info *server = cifs_pick_channel(tcon->ses);
1244+
struct cifsInodeInfo *cinode = CIFS_I(inode);
1245+
FILE_BASIC_INFO fi;
1246+
1247+
cinode->cifsAttrs &= ~(ATTR_TEMPORARY | ATTR_HIDDEN);
1248+
fi = (FILE_BASIC_INFO) {
1249+
.Attributes = cpu_to_le32(cinode->cifsAttrs),
1250+
};
1251+
return server->ops->set_file_info(inode, full_path, &fi, xid);
1252+
}
1253+
12401254
int smb2_create_hardlink(const unsigned int xid,
12411255
struct cifs_tcon *tcon,
12421256
struct dentry *source_dentry,
@@ -1246,24 +1260,14 @@ int smb2_create_hardlink(const unsigned int xid,
12461260
struct inode *inode = source_dentry ? d_inode(source_dentry) : NULL;
12471261
__u32 co = file_create_options(source_dentry);
12481262
struct cifsFileInfo *cfile;
1263+
int rc;
12491264

1250-
if (inode) {
1251-
struct cifsInodeInfo *cinode = CIFS_I(inode);
1252-
FILE_BASIC_INFO fi;
1253-
__le32 attrs;
1254-
int rc;
1255-
1256-
if (!test_bit(CIFS_INO_TMPFILE, &CIFS_I(inode)->flags))
1257-
goto out;
1258-
1259-
attrs = cpu_to_le32(cinode->cifsAttrs & ~ATTR_HIDDEN);
1260-
fi = (FILE_BASIC_INFO){ .Attributes = attrs, };
1261-
rc = smb2_set_file_info(inode, from_name, &fi, xid);
1265+
if (inode && test_bit(CIFS_INO_TMPFILE, &CIFS_I(inode)->flags)) {
1266+
rc = clear_tmpfile_attr(xid, tcon, inode, from_name);
12621267
if (rc)
12631268
return rc;
12641269
}
12651270

1266-
out:
12671271
cifs_get_writable_path(tcon, from_name, inode,
12681272
FIND_WITH_DELETE, &cfile);
12691273
return smb2_set_path_attr(xid, tcon, from_name, to_name,

0 commit comments

Comments
 (0)