if (!it->it_disposition) {
struct dentry *dentry = file_dentry(file);
struct ll_sb_info *sbi = ll_i2sbi(inode);
- struct ll_dentry_data *ldd;
+ int open_threshold = sbi->ll_oc_thrsh_count;
/* We cannot just request lock handle now, new ELC code
* means that one of other OPEN locks for this file
mutex_unlock(&lli->lli_och_mutex);
/*
* Normally called under two situations:
- * 1. NFS export.
+ * 1. fhandle / NFS export.
* 2. A race/condition on MDS resulting in no open
* handle to be returned from LOOKUP|OPEN request,
* for example if the target entry was a symlink.
*
- * In NFS path we know there's pathologic behavior
- * so we always enable open lock caching when coming
- * from there. It's detected by setting a flag in
- * ll_iget_for_nfs.
+ * For NFSv3 we need to always cache the open lock
+ * for pre 5.5 Linux kernels.
*
* After reaching number of opens of this inode
* we always ask for an open lock on it to handle
* bad userspace actors that open and close files
* in a loop for absolutely no good reason
*/
+ /* fhandle / NFS path. */
+ if (lli->lli_open_thrsh_count != UINT_MAX)
+ open_threshold = lli->lli_open_thrsh_count;
- ldd = ll_d2d(dentry);
if (filename_is_volatile(dentry->d_name.name,
dentry->d_name.len,
NULL)) {
* We do not want openlock for volatile
* files under any circumstances
*/
- } else if (ldd && ldd->lld_nfs_dentry) {
- /* NFS path. This also happens to catch
- * open by fh files I guess
- */
- it->it_flags |= MDS_OPEN_LOCK;
- /* clear the flag for future lookups */
- ldd->lld_nfs_dentry = 0;
- } else if (sbi->ll_oc_thrsh_count > 0) {
+ } else if (open_threshold > 0) {
/* Take MDS_OPEN_LOCK with many opens */
- if (lli->lli_open_fd_count >=
- sbi->ll_oc_thrsh_count)
+ if (lli->lli_open_fd_count >= open_threshold)
it->it_flags |= MDS_OPEN_LOCK;
/* If this is open after we just closed */
struct ll_dentry_data {
unsigned int lld_sa_generation;
unsigned int lld_invalid:1;
- unsigned int lld_nfs_dentry:1;
struct rcu_head lld_rcu_head;
};
__u64 lli_open_fd_write_count;
__u64 lli_open_fd_exec_count;
- /* Number of times this inode was opened */
- u64 lli_open_fd_count;
- /* When last close was performed on this inode */
- ktime_t lli_close_fd_time;
-
/* Protects access to och pointers and their usage counters */
struct mutex lli_och_mutex;
s64 lli_btime;
spinlock_t lli_agl_lock;
+ /* inode specific open lock caching threshold */
+ u32 lli_open_thrsh_count;
+ /* Number of times this inode was opened */
+ u64 lli_open_fd_count;
+ /* When last close was performed on this inode */
+ ktime_t lli_close_fd_time;
+
/* Try to make the d::member and f::member are aligned. Before using
* these members, make clear whether it is directory or not. */
union {
/* N.B. d_obtain_alias() drops inode ref on error */
result = d_obtain_alias(inode);
- if (!IS_ERR(result)) {
- struct ll_dentry_data *ldd;
+ if (IS_ERR(result))
+ RETURN(result);
- if (!ll_d_setup(result, true))
- RETURN(ERR_PTR(-ENOMEM));
- ldd = ll_d2d(result);
- /*
- * Need to signal to the ll_file_open that
- * we came from NFS and so opencache needs to be
- * enabled for this one
- */
- spin_lock(&result->d_lock);
- ldd->lld_nfs_dentry = 1;
- spin_unlock(&result->d_lock);
- }
+ if (!ll_d_setup(result, true))
+ RETURN(ERR_PTR(-ENOMEM));
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 5, 0)
+ /* If we are called by nfsd kthread set lli_open_thrsh_count
+ * to one. This will force caching the open lock. To be
+ * removed once oldest supported Linux kernel is 5.5
+ */
+ if ((current->flags & PF_KTHREAD) &&
+ strcmp(current->comm, "nfsd") == 0) {
+ struct ll_inode_info *lli = ll_i2info(inode);
+
+ lli->lli_open_thrsh_count = 1;
+ }
+#endif
RETURN(result);
}
struct ll_sb_info *sbi = NULL;
struct pcc_create_attach pca = { NULL, NULL };
bool encrypt = false;
+ int open_threshold;
int rc = 0;
- ENTRY;
+ ENTRY;
CDEBUG(D_VFSTRACE,
"VFS Op:name=%pd, dir="DFID"(%p), file %p, open_flags %x, mode %x opened %d\n",
dentry, PFID(ll_inode2fid(dir)), dir, file, open_flags, mode,
* we only need to request open lock if it was requested
* for every open
*/
- if (ll_i2sbi(dir)->ll_oc_thrsh_count == 1 &&
+ if (ll_i2info(dir)->lli_open_thrsh_count != UINT_MAX)
+ open_threshold = ll_i2info(dir)->lli_open_thrsh_count;
+ else
+ open_threshold = ll_i2sbi(dir)->ll_oc_thrsh_count;
+
+ if (open_threshold == 1 &&
exp_connect_flags2(ll_i2mdexp(dir)) &
OBD_CONNECT2_ATOMIC_OPEN_LOCK)
it->it_flags |= MDS_OPEN_LOCK;
return NULL;
#endif
inode_init_once(&lli->lli_vfs_inode);
+ lli->lli_open_thrsh_count = UINT_MAX;
+
return &lli->lli_vfs_inode;
}