static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl) { struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host); struct lm_lockname name = { .ln_number = ip->i_num.no_addr, .ln_type = LM_TYPE_PLOCK }; if (!(fl->fl_flags & FL_POSIX)) return -ENOLCK; if ((ip->i_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) return -ENOLCK; if (sdp->sd_args.ar_localflocks) { if (IS_GETLK(cmd)) { struct file_lock tmp; int ret; ret = posix_test_lock(file, fl, &tmp); fl->fl_type = F_UNLCK; if (ret) memcpy(fl, &tmp, sizeof(struct file_lock)); return 0; } else { return posix_lock_file_wait(file, fl); } } if (IS_GETLK(cmd)) return gfs2_lm_plock_get(sdp, &name, file, fl); else if (fl->fl_type == F_UNLCK) return gfs2_lm_punlock(sdp, &name, file, fl); else return gfs2_lm_plock(sdp, &name, file, cmd, fl); } static int do_flock(struct file *file, int cmd, struct file_lock *fl) { struct gfs2_file *fp = file->private_data; struct gfs2_holder *fl_gh = &fp->f_fl_gh; struct gfs2_inode *ip = GFS2_I(file->f_path.dentry->d_inode); struct gfs2_glock *gl; unsigned int state; int flags; int error = 0; state = (fl->fl_type == F_WRLCK) ? LM_ST_EXCLUSIVE : LM_ST_SHARED; flags = (IS_SETLKW(cmd) ? 0 : LM_FLAG_TRY) | GL_EXACT | GL_NOCACHE; mutex_lock(&fp->f_fl_mutex); gl = fl_gh->gh_gl; if (gl) { if (fl_gh->gh_state == state) goto out; gfs2_glock_hold(gl); flock_lock_file_wait(file, &(struct file_lock){.fl_type = F_UNLCK}); gfs2_glock_dq_uninit(fl_gh); } else {
/** * iopen_go_callback - schedule the dcache entry for the inode to be deleted * @gl: the glock * * gl_spin lock is held while calling this */ static void iopen_go_callback(struct gfs2_glock *gl) { struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; if (gl->gl_demote_state == LM_ST_UNLOCKED && gl->gl_state == LM_ST_SHARED && ip) { gfs2_glock_hold(gl); if (queue_work(gfs2_delete_workqueue, &gl->gl_delete) == 0) gfs2_glock_put_nolock(gl); } }
/** * iopen_go_callback - schedule the dcache entry for the inode to be deleted * @gl: the glock * * gl_spin lock is held while calling this */ static void iopen_go_callback(struct gfs2_glock *gl) { struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object; if (gl->gl_demote_state == LM_ST_UNLOCKED && gl->gl_state == LM_ST_SHARED && ip && test_bit(GIF_USER, &ip->i_flags)) { gfs2_glock_hold(gl); if (queue_delayed_work(gfs2_delete_workqueue, &gl->gl_delete, 0) == 0) gfs2_glock_put_nolock(gl); } }