// SPDX-License-Identifier: GPL-2.0-only /* * This file contians vfs file ops for 9P2000. * * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
*/
/** * v9fs_file_lock - lock a file (or directory) * @filp: file to be locked * @cmd: lock command * @fl: file lock structure * * Bugs: this looks like a local only lock, we should extend into 9P * by using open exclusive
*/
staticint v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl)
{ struct p9_flock flock; struct p9_fid *fid;
uint8_t status = P9_LOCK_ERROR; int res = 0; struct v9fs_session_info *v9ses;
fid = filp->private_data;
BUG_ON(fid == NULL);
BUG_ON((fl->c.flc_flags & FL_POSIX) != FL_POSIX);
res = locks_lock_file_wait(filp, fl); if (res < 0) goto out;
/* convert posix lock to p9 tlock args */
memset(&flock, 0, sizeof(flock)); /* map the lock type */ switch (fl->c.flc_type) { case F_RDLCK:
flock.type = P9_LOCK_TYPE_RDLCK; break; case F_WRLCK:
flock.type = P9_LOCK_TYPE_WRLCK; break; case F_UNLCK:
flock.type = P9_LOCK_TYPE_UNLCK; break;
}
flock.start = fl->fl_start; if (fl->fl_end == OFFSET_MAX)
flock.length = 0; else
flock.length = fl->fl_end - fl->fl_start + 1;
flock.proc_id = fl->c.flc_pid;
flock.client_id = fid->clnt->name; if (IS_SETLKW(cmd))
flock.flags = P9_LOCK_FLAGS_BLOCK;
v9ses = v9fs_inode2v9ses(file_inode(filp));
/* * if its a blocked request and we get P9_LOCK_BLOCKED as the status * for lock request, keep on trying
*/ for (;;) {
res = p9_client_lock_dotl(fid, &flock, &status); if (res < 0) goto out_unlock;
if (status != P9_LOCK_BLOCKED) break; if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd)) break; if (schedule_timeout_interruptible(v9ses->session_lock_timeout)
!= 0) break; /* * p9_client_lock_dotl overwrites flock.client_id with the * server message, free and reuse the client name
*/ if (flock.client_id != fid->clnt->name) {
kfree(flock.client_id);
flock.client_id = fid->clnt->name;
}
}
/* map 9p status to VFS status */ switch (status) { case P9_LOCK_SUCCESS:
res = 0; break; case P9_LOCK_BLOCKED:
res = -EAGAIN; break; default:
WARN_ONCE(1, "unknown lock status code: %d\n", status);
fallthrough; case P9_LOCK_ERROR: case P9_LOCK_GRACE:
res = -ENOLCK; break;
}
out_unlock: /* * incase server returned error for lock request, revert * it locally
*/ if (res < 0 && fl->c.flc_type != F_UNLCK) { unsignedchar type = fl->c.flc_type;
fl->c.flc_type = F_UNLCK; /* Even if this fails we want to return the remote error */
locks_lock_file_wait(filp, fl);
fl->c.flc_type = type;
} if (flock.client_id != fid->clnt->name)
kfree(flock.client_id);
out: return res;
}
staticint v9fs_file_getlock(struct file *filp, struct file_lock *fl)
{ struct p9_getlock glock; struct p9_fid *fid; int res = 0;
fid = filp->private_data;
BUG_ON(fid == NULL);
posix_test_lock(filp, fl); /* * if we have a conflicting lock locally, no need to validate * with server
*/ if (fl->c.flc_type != F_UNLCK) return res;
/* * v9fs_file_splice_read - splice-read from a file * @in: The 9p file to read from * @ppos: Where to find/update the file position * @pipe: The pipe to splice into * @len: The maximum amount of data to splice * @flags: SPLICE_F_* flags
*/ static ssize_t v9fs_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe,
size_t len, unsignedint flags)
{ struct p9_fid *fid = in->private_data;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.