Skip to content

Commit 3e7d630

Browse files
pcacjrsmfrench
authored andcommitted
smb: client: add support for O_TMPFILE
Implement O_TMPFILE support for SMB2+ in the CIFS client. Signed-off-by: Paulo Alcantara (Red Hat) <pc@manguebit.org> Cc: David Howells <dhowells@redhat.com> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: linux-fsdevel@vger.kernel.org Cc: linux-cifs@vger.kernel.org Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent 30a59dd commit 3e7d630

9 files changed

Lines changed: 490 additions & 325 deletions

File tree

fs/smb/client/cifsfs.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ MODULE_PARM_DESC(dir_cache_timeout, "Number of seconds to cache directory conten
124124
/* Module-wide total cached dirents (in bytes) across all tcons */
125125
atomic64_t cifs_dircache_bytes_used = ATOMIC64_INIT(0);
126126

127+
atomic_t cifs_sillycounter;
128+
atomic_t cifs_tmpcounter;
129+
127130
/*
128131
* Write-only module parameter to drop all cached directory entries across
129132
* all CIFS mounts. Echo a non-zero value to trigger.
@@ -1199,6 +1202,7 @@ MODULE_ALIAS("smb3");
11991202
const struct inode_operations cifs_dir_inode_ops = {
12001203
.create = cifs_create,
12011204
.atomic_open = cifs_atomic_open,
1205+
.tmpfile = cifs_tmpfile,
12021206
.lookup = cifs_lookup,
12031207
.getattr = cifs_getattr,
12041208
.unlink = cifs_unlink,

fs/smb/client/cifsfs.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
#define ROOT_I 2
1515

16+
extern atomic_t cifs_sillycounter;
17+
extern atomic_t cifs_tmpcounter;
18+
1619
/*
1720
* ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down
1821
* so that it will fit. We use hash_64 to convert the value to 31 bits, and
@@ -53,6 +56,8 @@ int cifs_create(struct mnt_idmap *idmap, struct inode *inode,
5356
struct dentry *direntry, umode_t mode, bool excl);
5457
int cifs_atomic_open(struct inode *inode, struct dentry *direntry,
5558
struct file *file, unsigned int oflags, umode_t mode);
59+
int cifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
60+
struct file *file, umode_t mode);
5661
struct dentry *cifs_lookup(struct inode *parent_dir_inode,
5762
struct dentry *direntry, unsigned int flags);
5863
int cifs_unlink(struct inode *dir, struct dentry *dentry);
@@ -142,6 +147,20 @@ struct smb3_fs_context;
142147
struct dentry *cifs_smb3_do_mount(struct file_system_type *fs_type, int flags,
143148
struct smb3_fs_context *old_ctx);
144149

150+
char *cifs_silly_fullpath(struct dentry *dentry);
151+
152+
#define CIFS_TMPNAME_PREFIX ".__smbfile_tmp"
153+
#define CIFS_TMPNAME_PREFIX_LEN ((int)sizeof(CIFS_TMPNAME_PREFIX) - 1)
154+
#define CIFS_TMPNAME_COUNTER_LEN ((int)sizeof(cifs_tmpcounter) * 2)
155+
#define CIFS_TMPNAME_LEN \
156+
(CIFS_TMPNAME_PREFIX_LEN + CIFS_TMPNAME_COUNTER_LEN)
157+
158+
#define CIFS_SILLYNAME_PREFIX ".__smbfile_silly"
159+
#define CIFS_SILLYNAME_PREFIX_LEN ((int)sizeof(CIFS_SILLYNAME_PREFIX) - 1)
160+
#define CIFS_SILLYNAME_COUNTER_LEN ((int)sizeof(cifs_sillycounter) * 2)
161+
#define CIFS_SILLYNAME_LEN \
162+
(CIFS_SILLYNAME_PREFIX_LEN + CIFS_SILLYNAME_COUNTER_LEN)
163+
145164
#ifdef CONFIG_CIFS_NFSD_EXPORT
146165
extern const struct export_operations cifs_export_ops;
147166
#endif /* CONFIG_CIFS_NFSD_EXPORT */

fs/smb/client/cifsglob.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1534,9 +1534,16 @@ int cifs_file_set_size(const unsigned int xid, struct dentry *dentry,
15341534
#define CIFS_CACHE_RW_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG)
15351535
#define CIFS_CACHE_RHW_FLG (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG)
15361536

1537-
/*
1538-
* One of these for each file inode
1539-
*/
1537+
enum cifs_inode_flags {
1538+
CIFS_INODE_PENDING_OPLOCK_BREAK, /* oplock break in progress */
1539+
CIFS_INODE_PENDING_WRITERS, /* Writes in progress */
1540+
CIFS_INODE_FLAG_UNUSED, /* Unused flag */
1541+
CIFS_INO_DELETE_PENDING, /* delete pending on server */
1542+
CIFS_INO_INVALID_MAPPING, /* pagecache is invalid */
1543+
CIFS_INO_LOCK, /* lock bit for synchronization */
1544+
CIFS_INO_TMPFILE, /* for O_TMPFILE inodes */
1545+
CIFS_INO_CLOSE_ON_LOCK, /* Not to defer the close when lock is set */
1546+
};
15401547

15411548
struct cifsInodeInfo {
15421549
struct netfs_inode netfs; /* Netfslib context and vfs inode */
@@ -1554,13 +1561,6 @@ struct cifsInodeInfo {
15541561
__u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
15551562
unsigned int oplock; /* oplock/lease level we have */
15561563
__u16 epoch; /* used to track lease state changes */
1557-
#define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */
1558-
#define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */
1559-
#define CIFS_INODE_FLAG_UNUSED (2) /* Unused flag */
1560-
#define CIFS_INO_DELETE_PENDING (3) /* delete pending on server */
1561-
#define CIFS_INO_INVALID_MAPPING (4) /* pagecache is invalid */
1562-
#define CIFS_INO_LOCK (5) /* lock bit for synchronization */
1563-
#define CIFS_INO_CLOSE_ON_LOCK (7) /* Not to defer the close when lock is set */
15641564
unsigned long flags;
15651565
spinlock_t writers_lock;
15661566
unsigned int writers; /* Number of writers on this inode */
@@ -2259,6 +2259,7 @@ struct smb2_compound_vars {
22592259
struct kvec qi_iov;
22602260
struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
22612261
struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
2262+
struct kvec hl_iov[SMB2_SET_INFO_IOV_SIZE];
22622263
struct kvec unlink_iov[SMB2_SET_INFO_IOV_SIZE];
22632264
struct kvec rename_iov[SMB2_SET_INFO_IOV_SIZE];
22642265
struct kvec close_iov;
@@ -2383,6 +2384,8 @@ static inline int cifs_open_create_options(unsigned int oflags, int opts)
23832384
opts |= CREATE_WRITE_THROUGH;
23842385
if (oflags & O_DIRECT)
23852386
opts |= CREATE_NO_BUFFER;
2387+
if (oflags & O_TMPFILE)
2388+
opts |= CREATE_DELETE_ON_CLOSE;
23862389
return opts;
23872390
}
23882391

fs/smb/client/cifsproto.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode,
141141
int __cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
142142
unsigned int find_flags, unsigned int open_flags,
143143
struct cifsFileInfo **ret_file);
144-
int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, int flags,
144+
int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
145+
struct inode *inode, int flags,
145146
struct cifsFileInfo **ret_file);
146147
struct cifsFileInfo *__find_readable_file(struct cifsInodeInfo *cifs_inode,
147148
unsigned int find_flags,

0 commit comments

Comments
 (0)