Skip to content

Commit c7d7d2d

Browse files
author
Andreas Gruenbacher
committed
gfs2: Merge branch 'for-next.nopid' into for-next
Resolves a conflict in gfs2_inode_lookup() between the following commits: gfs2: Use TRY lock in gfs2_inode_lookup for UNLINKED inodes gfs2: Mark the remaining process-independent glock holders as GL_NOPID Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
2 parents 74b1b10 + ebdc416 commit c7d7d2d

File tree

9 files changed

+248
-25
lines changed

9 files changed

+248
-25
lines changed

fs/file.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,7 @@ struct file *task_lookup_next_fd_rcu(struct task_struct *task, unsigned int *ret
980980
*ret_fd = fd;
981981
return file;
982982
}
983+
EXPORT_SYMBOL(task_lookup_next_fd_rcu);
983984

984985
/*
985986
* Lightweight file lookup - no refcnt increment if fd table isn't shared.

fs/gfs2/file.c

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,22 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
14431443
return dlm_posix_lock(ls->ls_dlm, ip->i_no_addr, file, cmd, fl);
14441444
}
14451445

1446+
static void __flock_holder_uninit(struct file *file, struct gfs2_holder *fl_gh)
1447+
{
1448+
struct gfs2_glock *gl = fl_gh->gh_gl;
1449+
1450+
/*
1451+
* Make sure gfs2_glock_put() won't sleep under the file->f_lock
1452+
* spinlock.
1453+
*/
1454+
1455+
gfs2_glock_hold(gl);
1456+
spin_lock(&file->f_lock);
1457+
gfs2_holder_uninit(fl_gh);
1458+
spin_unlock(&file->f_lock);
1459+
gfs2_glock_put(gl);
1460+
}
1461+
14461462
static int do_flock(struct file *file, int cmd, struct file_lock *fl)
14471463
{
14481464
struct gfs2_file *fp = file->private_data;
@@ -1455,7 +1471,9 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
14551471
int sleeptime;
14561472

14571473
state = (fl->fl_type == F_WRLCK) ? LM_ST_EXCLUSIVE : LM_ST_SHARED;
1458-
flags = (IS_SETLKW(cmd) ? 0 : LM_FLAG_TRY_1CB) | GL_EXACT;
1474+
flags = GL_EXACT | GL_NOPID;
1475+
if (!IS_SETLKW(cmd))
1476+
flags |= LM_FLAG_TRY_1CB;
14591477

14601478
mutex_lock(&fp->f_fl_mutex);
14611479

@@ -1474,18 +1492,21 @@ static int do_flock(struct file *file, int cmd, struct file_lock *fl)
14741492
&gfs2_flock_glops, CREATE, &gl);
14751493
if (error)
14761494
goto out;
1495+
spin_lock(&file->f_lock);
14771496
gfs2_holder_init(gl, state, flags, fl_gh);
1497+
spin_unlock(&file->f_lock);
14781498
gfs2_glock_put(gl);
14791499
}
14801500
for (sleeptime = 1; sleeptime <= 4; sleeptime <<= 1) {
14811501
error = gfs2_glock_nq(fl_gh);
14821502
if (error != GLR_TRYFAILED)
14831503
break;
1484-
fl_gh->gh_flags = LM_FLAG_TRY | GL_EXACT;
1504+
fl_gh->gh_flags &= ~LM_FLAG_TRY_1CB;
1505+
fl_gh->gh_flags |= LM_FLAG_TRY;
14851506
msleep(sleeptime);
14861507
}
14871508
if (error) {
1488-
gfs2_holder_uninit(fl_gh);
1509+
__flock_holder_uninit(file, fl_gh);
14891510
if (error == GLR_TRYFAILED)
14901511
error = -EAGAIN;
14911512
} else {
@@ -1507,7 +1528,7 @@ static void do_unflock(struct file *file, struct file_lock *fl)
15071528
locks_lock_file_wait(file, fl);
15081529
if (gfs2_holder_initialized(fl_gh)) {
15091530
gfs2_glock_dq(fl_gh);
1510-
gfs2_holder_uninit(fl_gh);
1531+
__flock_holder_uninit(file, fl_gh);
15111532
}
15121533
mutex_unlock(&fp->f_fl_mutex);
15131534
}

fs/gfs2/glock.c

Lines changed: 203 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#include <linux/list_sort.h>
3434
#include <linux/lockref.h>
3535
#include <linux/rhashtable.h>
36+
#include <linux/pid_namespace.h>
37+
#include <linux/fdtable.h>
38+
#include <linux/file.h>
3639

3740
#include "gfs2.h"
3841
#include "incore.h"
@@ -1456,6 +1459,15 @@ void gfs2_print_dbg(struct seq_file *seq, const char *fmt, ...)
14561459
va_end(args);
14571460
}
14581461

1462+
static inline bool pid_is_meaningful(const struct gfs2_holder *gh)
1463+
{
1464+
if (!(gh->gh_flags & GL_NOPID))
1465+
return true;
1466+
if (gh->gh_state == LM_ST_UNLOCKED)
1467+
return true;
1468+
return false;
1469+
}
1470+
14591471
/**
14601472
* add_to_queue - Add a holder to the wait queue (but look for recursion)
14611473
* @gh: the holder structure to add
@@ -1492,10 +1504,17 @@ __acquires(&gl->gl_lockref.lock)
14921504
}
14931505

14941506
list_for_each_entry(gh2, &gl->gl_holders, gh_list) {
1495-
if (unlikely(gh2->gh_owner_pid == gh->gh_owner_pid &&
1496-
(gh->gh_gl->gl_ops->go_type != LM_TYPE_FLOCK) &&
1497-
!test_bit(HIF_MAY_DEMOTE, &gh2->gh_iflags)))
1498-
goto trap_recursive;
1507+
if (likely(gh2->gh_owner_pid != gh->gh_owner_pid))
1508+
continue;
1509+
if (gh->gh_gl->gl_ops->go_type == LM_TYPE_FLOCK)
1510+
continue;
1511+
if (test_bit(HIF_MAY_DEMOTE, &gh2->gh_iflags))
1512+
continue;
1513+
if (!pid_is_meaningful(gh2))
1514+
continue;
1515+
goto trap_recursive;
1516+
}
1517+
list_for_each_entry(gh2, &gl->gl_holders, gh_list) {
14991518
if (try_futile &&
15001519
!(gh2->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))) {
15011520
fail:
@@ -2306,19 +2325,24 @@ static const char *hflags2str(char *buf, u16 flags, unsigned long iflags)
23062325
static void dump_holder(struct seq_file *seq, const struct gfs2_holder *gh,
23072326
const char *fs_id_buf)
23082327
{
2309-
struct task_struct *gh_owner = NULL;
2328+
const char *comm = "(none)";
2329+
pid_t owner_pid = 0;
23102330
char flags_buf[32];
23112331

23122332
rcu_read_lock();
2313-
if (gh->gh_owner_pid)
2333+
if (pid_is_meaningful(gh)) {
2334+
struct task_struct *gh_owner;
2335+
2336+
comm = "(ended)";
2337+
owner_pid = pid_nr(gh->gh_owner_pid);
23142338
gh_owner = pid_task(gh->gh_owner_pid, PIDTYPE_PID);
2339+
if (gh_owner)
2340+
comm = gh_owner->comm;
2341+
}
23152342
gfs2_print_dbg(seq, "%s H: s:%s f:%s e:%d p:%ld [%s] %pS\n",
23162343
fs_id_buf, state2str(gh->gh_state),
23172344
hflags2str(flags_buf, gh->gh_flags, gh->gh_iflags),
2318-
gh->gh_error,
2319-
gh->gh_owner_pid ? (long)pid_nr(gh->gh_owner_pid) : -1,
2320-
gh_owner ? gh_owner->comm : "(ended)",
2321-
(void *)gh->gh_ip);
2345+
gh->gh_error, (long)owner_pid, comm, (void *)gh->gh_ip);
23222346
rcu_read_unlock();
23232347
}
23242348

@@ -2733,6 +2757,172 @@ static const struct file_operations gfs2_glstats_fops = {
27332757
.release = gfs2_glocks_release,
27342758
};
27352759

2760+
struct gfs2_glockfd_iter {
2761+
struct super_block *sb;
2762+
unsigned int tgid;
2763+
struct task_struct *task;
2764+
unsigned int fd;
2765+
struct file *file;
2766+
};
2767+
2768+
static struct task_struct *gfs2_glockfd_next_task(struct gfs2_glockfd_iter *i)
2769+
{
2770+
struct pid_namespace *ns = task_active_pid_ns(current);
2771+
struct pid *pid;
2772+
2773+
if (i->task)
2774+
put_task_struct(i->task);
2775+
2776+
rcu_read_lock();
2777+
retry:
2778+
i->task = NULL;
2779+
pid = find_ge_pid(i->tgid, ns);
2780+
if (pid) {
2781+
i->tgid = pid_nr_ns(pid, ns);
2782+
i->task = pid_task(pid, PIDTYPE_TGID);
2783+
if (!i->task) {
2784+
i->tgid++;
2785+
goto retry;
2786+
}
2787+
get_task_struct(i->task);
2788+
}
2789+
rcu_read_unlock();
2790+
return i->task;
2791+
}
2792+
2793+
static struct file *gfs2_glockfd_next_file(struct gfs2_glockfd_iter *i)
2794+
{
2795+
if (i->file) {
2796+
fput(i->file);
2797+
i->file = NULL;
2798+
}
2799+
2800+
rcu_read_lock();
2801+
for(;; i->fd++) {
2802+
struct inode *inode;
2803+
2804+
i->file = task_lookup_next_fd_rcu(i->task, &i->fd);
2805+
if (!i->file) {
2806+
i->fd = 0;
2807+
break;
2808+
}
2809+
inode = file_inode(i->file);
2810+
if (inode->i_sb != i->sb)
2811+
continue;
2812+
if (get_file_rcu(i->file))
2813+
break;
2814+
}
2815+
rcu_read_unlock();
2816+
return i->file;
2817+
}
2818+
2819+
static void *gfs2_glockfd_seq_start(struct seq_file *seq, loff_t *pos)
2820+
{
2821+
struct gfs2_glockfd_iter *i = seq->private;
2822+
2823+
if (*pos)
2824+
return NULL;
2825+
while (gfs2_glockfd_next_task(i)) {
2826+
if (gfs2_glockfd_next_file(i))
2827+
return i;
2828+
i->tgid++;
2829+
}
2830+
return NULL;
2831+
}
2832+
2833+
static void *gfs2_glockfd_seq_next(struct seq_file *seq, void *iter_ptr,
2834+
loff_t *pos)
2835+
{
2836+
struct gfs2_glockfd_iter *i = seq->private;
2837+
2838+
(*pos)++;
2839+
i->fd++;
2840+
do {
2841+
if (gfs2_glockfd_next_file(i))
2842+
return i;
2843+
i->tgid++;
2844+
} while (gfs2_glockfd_next_task(i));
2845+
return NULL;
2846+
}
2847+
2848+
static void gfs2_glockfd_seq_stop(struct seq_file *seq, void *iter_ptr)
2849+
{
2850+
struct gfs2_glockfd_iter *i = seq->private;
2851+
2852+
if (i->file)
2853+
fput(i->file);
2854+
if (i->task)
2855+
put_task_struct(i->task);
2856+
}
2857+
2858+
static void gfs2_glockfd_seq_show_flock(struct seq_file *seq,
2859+
struct gfs2_glockfd_iter *i)
2860+
{
2861+
struct gfs2_file *fp = i->file->private_data;
2862+
struct gfs2_holder *fl_gh = &fp->f_fl_gh;
2863+
struct lm_lockname gl_name = { .ln_type = LM_TYPE_RESERVED };
2864+
2865+
if (!READ_ONCE(fl_gh->gh_gl))
2866+
return;
2867+
2868+
spin_lock(&i->file->f_lock);
2869+
if (gfs2_holder_initialized(fl_gh))
2870+
gl_name = fl_gh->gh_gl->gl_name;
2871+
spin_unlock(&i->file->f_lock);
2872+
2873+
if (gl_name.ln_type != LM_TYPE_RESERVED) {
2874+
seq_printf(seq, "%d %u %u/%llx\n",
2875+
i->tgid, i->fd, gl_name.ln_type,
2876+
(unsigned long long)gl_name.ln_number);
2877+
}
2878+
}
2879+
2880+
static int gfs2_glockfd_seq_show(struct seq_file *seq, void *iter_ptr)
2881+
{
2882+
struct gfs2_glockfd_iter *i = seq->private;
2883+
struct inode *inode = file_inode(i->file);
2884+
struct gfs2_glock *gl;
2885+
2886+
inode_lock_shared(inode);
2887+
gl = GFS2_I(inode)->i_iopen_gh.gh_gl;
2888+
if (gl) {
2889+
seq_printf(seq, "%d %u %u/%llx\n",
2890+
i->tgid, i->fd, gl->gl_name.ln_type,
2891+
(unsigned long long)gl->gl_name.ln_number);
2892+
}
2893+
gfs2_glockfd_seq_show_flock(seq, i);
2894+
inode_unlock_shared(inode);
2895+
return 0;
2896+
}
2897+
2898+
static const struct seq_operations gfs2_glockfd_seq_ops = {
2899+
.start = gfs2_glockfd_seq_start,
2900+
.next = gfs2_glockfd_seq_next,
2901+
.stop = gfs2_glockfd_seq_stop,
2902+
.show = gfs2_glockfd_seq_show,
2903+
};
2904+
2905+
static int gfs2_glockfd_open(struct inode *inode, struct file *file)
2906+
{
2907+
struct gfs2_glockfd_iter *i;
2908+
struct gfs2_sbd *sdp = inode->i_private;
2909+
2910+
i = __seq_open_private(file, &gfs2_glockfd_seq_ops,
2911+
sizeof(struct gfs2_glockfd_iter));
2912+
if (!i)
2913+
return -ENOMEM;
2914+
i->sb = sdp->sd_vfs;
2915+
return 0;
2916+
}
2917+
2918+
static const struct file_operations gfs2_glockfd_fops = {
2919+
.owner = THIS_MODULE,
2920+
.open = gfs2_glockfd_open,
2921+
.read = seq_read,
2922+
.llseek = seq_lseek,
2923+
.release = seq_release_private,
2924+
};
2925+
27362926
DEFINE_SEQ_ATTRIBUTE(gfs2_sbstats);
27372927

27382928
void gfs2_create_debugfs_file(struct gfs2_sbd *sdp)
@@ -2742,6 +2932,9 @@ void gfs2_create_debugfs_file(struct gfs2_sbd *sdp)
27422932
debugfs_create_file("glocks", S_IFREG | S_IRUGO, sdp->debugfs_dir, sdp,
27432933
&gfs2_glocks_fops);
27442934

2935+
debugfs_create_file("glockfd", S_IFREG | S_IRUGO, sdp->debugfs_dir, sdp,
2936+
&gfs2_glockfd_fops);
2937+
27452938
debugfs_create_file("glstats", S_IFREG | S_IRUGO, sdp->debugfs_dir, sdp,
27462939
&gfs2_glstats_fops);
27472940

fs/gfs2/glock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ enum {
9191
#define GL_ASYNC 0x0040
9292
#define GL_EXACT 0x0080
9393
#define GL_SKIP 0x0100
94+
#define GL_NOPID 0x0200
9495
#define GL_NOCACHE 0x0400
9596

9697
/*

fs/gfs2/inode.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
147147
else
148148
gfs2_cancel_delete_work(io_gl);
149149
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED,
150-
GL_EXACT | extra_flags,
150+
GL_EXACT | GL_NOPID | extra_flags,
151151
&ip->i_iopen_gh);
152152
gfs2_glock_put(io_gl);
153153
if (unlikely(error))
@@ -726,7 +726,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry,
726726
error = insert_inode_locked4(inode, ip->i_no_addr, iget_test, &ip->i_no_addr);
727727
BUG_ON(error);
728728

729-
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT, &ip->i_iopen_gh);
729+
error = gfs2_glock_nq_init(io_gl, LM_ST_SHARED, GL_EXACT | GL_NOPID,
730+
&ip->i_iopen_gh);
730731
if (error)
731732
goto fail_gunlock2;
732733

0 commit comments

Comments
 (0)