From 4f7ebe807242898ee08ed732d56982874442c304 Mon Sep 17 00:00:00 2001 From: Arun R Bharadwaj Date: Wed, 28 Jul 2010 14:17:26 +0530 Subject: net/9p: This patch implements TLERROR/RLERROR on the 9P client. Signed-off-by: Arun R Bharadwaj Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- include/net/9p/9p.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index a8de812ccbc8..a4a1b043a8c4 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -86,6 +86,8 @@ do { \ /** * enum p9_msg_t - 9P message types + * @P9_TLERROR: not used + * @P9_RLERROR: response for any failed request for 9P2000.L * @P9_TSTATFS: file system status request * @P9_RSTATFS: file system status response * @P9_TSYMLINK: make symlink request @@ -137,6 +139,8 @@ do { \ */ enum p9_msg_t { + P9_TLERROR = 6, + P9_RLERROR, P9_TSTATFS = 8, P9_RSTATFS, P9_TLOPEN = 12, -- cgit v1.2.3-59-g8ed1b From 920e65dc6911da28a58e17f4b683302636fc6d8e Mon Sep 17 00:00:00 2001 From: "Venkateswararao Jujjuri (JV)" Date: Wed, 22 Sep 2010 17:19:19 -0700 Subject: [9p] Introduce client side TFSYNC/RFSYNC for dotl. SYNOPSIS size[4] Tfsync tag[2] fid[4] size[4] Rfsync tag[2] DESCRIPTION The Tfsync transaction transfers ("flushes") all modified in-core data of file identified by fid to the disk device (or other permanent storage device) where that file resides. Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_file.c | 18 ++++++++++++++++-- include/net/9p/9p.h | 2 ++ include/net/9p/client.h | 1 + net/9p/client.c | 25 +++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 28db7fb1d96e..fdf303207c72 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -290,6 +290,20 @@ static int v9fs_file_fsync(struct file *filp, int datasync) return retval; } +static int v9fs_file_fsync_dotl(struct file *filp, int datasync) +{ + struct p9_fid *fid; + int retval; + + P9_DPRINTK(P9_DEBUG_VFS, "v9fs_file_fsync_dotl: filp %p datasync %x\n", + filp, datasync); + + fid = filp->private_data; + + retval = p9_client_fsync(fid); + return retval; +} + static const struct file_operations v9fs_cached_file_operations = { .llseek = generic_file_llseek, .read = do_sync_read, @@ -311,7 +325,7 @@ static const struct file_operations v9fs_cached_file_operations_dotl = { .release = v9fs_dir_release, .lock = v9fs_file_lock, .mmap = generic_file_readonly_mmap, - .fsync = v9fs_file_fsync, + .fsync = v9fs_file_fsync_dotl, }; const struct file_operations v9fs_file_operations = { @@ -333,5 +347,5 @@ const struct file_operations v9fs_file_operations_dotl = { .release = v9fs_dir_release, .lock = v9fs_file_lock, .mmap = generic_file_readonly_mmap, - .fsync = v9fs_file_fsync, + .fsync = v9fs_file_fsync_dotl, }; diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index a4a1b043a8c4..55e96057f47f 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -163,6 +163,8 @@ enum p9_msg_t { P9_RXATTRCREATE, P9_TREADDIR = 40, P9_RREADDIR, + P9_TFSYNC = 50, + P9_RFSYNC, P9_TLINK = 70, P9_RLINK, P9_TMKDIR = 72, diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 7f63d5ab7b44..8744e3ad4a07 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -229,6 +229,7 @@ int p9_client_symlink(struct p9_fid *fid, char *name, char *symname, gid_t gid, int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode, gid_t gid, struct p9_qid *qid); int p9_client_clunk(struct p9_fid *fid); +int p9_client_fsync(struct p9_fid *fid); int p9_client_remove(struct p9_fid *fid); int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, u32 count); diff --git a/net/9p/client.c b/net/9p/client.c index e50ec802937a..30c4a1b224fb 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1162,6 +1162,31 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname) } EXPORT_SYMBOL(p9_client_link); +int p9_client_fsync(struct p9_fid *fid) +{ + int err; + struct p9_client *clnt; + struct p9_req_t *req; + + P9_DPRINTK(P9_DEBUG_9P, ">>> TFSYNC fid %d\n", fid->fid); + err = 0; + clnt = fid->clnt; + + req = p9_client_rpc(clnt, P9_TFSYNC, "d", fid->fid); + if (IS_ERR(req)) { + err = PTR_ERR(req); + goto error; + } + + P9_DPRINTK(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid); + + p9_free_req(clnt, req); + +error: + return err; +} +EXPORT_SYMBOL(p9_client_fsync); + int p9_client_clunk(struct p9_fid *fid) { int err; -- cgit v1.2.3-59-g8ed1b From a099027c779068b834f335cfdc3f2bf10f531dd9 Mon Sep 17 00:00:00 2001 From: "M. Mohan Kumar" Date: Mon, 27 Sep 2010 11:34:24 +0530 Subject: 9p: Implement TLOCK Synopsis size[4] TLock tag[2] fid[4] flock[n] size[4] RLock tag[2] status[1] Description Tlock is used to acquire/release byte range posix locks on a file identified by given fid. The reply contains status of the lock request flock structure: type[1] - Type of lock: F_RDLCK, F_WRLCK, F_UNLCK flags[4] - Flags could be either of P9_LOCK_FLAGS_BLOCK - Blocked lock request, if there is a conflicting lock exists, wait for that lock to be released. P9_LOCK_FLAGS_RECLAIM - Reclaim lock request, used when client is trying to reclaim a lock after a server restrart (due to crash) start[8] - Starting offset for lock length[8] - Number of bytes to lock If length is 0, lock all bytes starting at the location 'start' through to the end of file pid[4] - PID of the process that wants to take lock client_id[4] - Unique client id status[1] - Status of the lock request, can be P9_LOCK_SUCCESS(0), P9_LOCK_BLOCKED(1), P9_LOCK_ERROR(2) or P9_LOCK_GRACE(3) P9_LOCK_SUCCESS - Request was successful P9_LOCK_BLOCKED - A conflicting lock is held by another process P9_LOCK_ERROR - Error while processing the lock request P9_LOCK_GRACE - Server is in grace period, it can't accept new lock requests in this period (except locks with P9_LOCK_FLAGS_RECLAIM flag set) Signed-off-by: M. Mohan Kumar Signed-off-by: Aneesh Kumar K.V Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/v9fs_vfs.h | 2 + fs/9p/vfs_file.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++- include/net/9p/9p.h | 28 +++++++++ include/net/9p/client.h | 1 + net/9p/client.c | 33 ++++++++++ 5 files changed, 222 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index 09861295eef9..d26db1932f7a 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -65,3 +65,5 @@ int v9fs_uflags2omode(int uflags, int extended); ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64); void v9fs_blank_wstat(struct p9_wstat *wstat); int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); + +#define P9_LOCK_TIMEOUT (30*HZ) diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index fdf303207c72..6f77abd23184 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -133,6 +134,159 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) return res; } +static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) +{ + struct p9_flock flock; + struct p9_fid *fid; + uint8_t status; + int res = 0; + unsigned char fl_type; + + fid = filp->private_data; + BUG_ON(fid == NULL); + + if ((fl->fl_flags & FL_POSIX) != FL_POSIX) + BUG(); + + res = posix_lock_file_wait(filp, fl); + if (res < 0) + goto out; + + /* convert posix lock to p9 tlock args */ + memset(&flock, 0, sizeof(flock)); + flock.type = fl->fl_type; + 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->fl_pid; + flock.client_id = utsname()->nodename; + if (IS_SETLKW(cmd)) + flock.flags = P9_LOCK_FLAGS_BLOCK; + + /* + * 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) + break; + + if (status != P9_LOCK_BLOCKED) + break; + if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd)) + break; + schedule_timeout_interruptible(P9_LOCK_TIMEOUT); + } + + /* map 9p status to VFS status */ + switch (status) { + case P9_LOCK_SUCCESS: + res = 0; + break; + case P9_LOCK_BLOCKED: + res = -EAGAIN; + break; + case P9_LOCK_ERROR: + case P9_LOCK_GRACE: + res = -ENOLCK; + break; + default: + BUG(); + } + + /* + * incase server returned error for lock request, revert + * it locally + */ + if (res < 0 && fl->fl_type != F_UNLCK) { + fl_type = fl->fl_type; + fl->fl_type = F_UNLCK; + res = posix_lock_file_wait(filp, fl); + fl->fl_type = fl_type; + } +out: + return res; +} + +/** + * v9fs_file_lock_dotl - lock a file (or directory) + * @filp: file to be locked + * @cmd: lock command + * @fl: file lock structure + * + */ + +static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl) +{ + struct inode *inode = filp->f_path.dentry->d_inode; + int ret = -ENOLCK; + + P9_DPRINTK(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", filp, + cmd, fl, filp->f_path.dentry->d_name.name); + + /* No mandatory locks */ + if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) + goto out_err; + + if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { + filemap_write_and_wait(inode->i_mapping); + invalidate_mapping_pages(&inode->i_data, 0, -1); + } + + if (IS_SETLK(cmd) || IS_SETLKW(cmd)) + ret = v9fs_file_do_lock(filp, cmd, fl); + else + ret = -EINVAL; +out_err: + return ret; +} + +/** + * v9fs_file_flock_dotl - lock a file + * @filp: file to be locked + * @cmd: lock command + * @fl: file lock structure + * + */ + +static int v9fs_file_flock_dotl(struct file *filp, int cmd, + struct file_lock *fl) +{ + struct inode *inode = filp->f_path.dentry->d_inode; + int ret = -ENOLCK; + + P9_DPRINTK(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", filp, + cmd, fl, filp->f_path.dentry->d_name.name); + + /* No mandatory locks */ + if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) + goto out_err; + + if (!(fl->fl_flags & FL_FLOCK)) + goto out_err; + + if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { + filemap_write_and_wait(inode->i_mapping); + invalidate_mapping_pages(&inode->i_data, 0, -1); + } + /* Convert flock to posix lock */ + fl->fl_owner = (fl_owner_t)filp; + fl->fl_start = 0; + fl->fl_end = OFFSET_MAX; + fl->fl_flags |= FL_POSIX; + fl->fl_flags ^= FL_FLOCK; + + if (IS_SETLK(cmd) | IS_SETLKW(cmd)) + ret = v9fs_file_do_lock(filp, cmd, fl); + else + ret = -EINVAL; +out_err: + return ret; +} + /** * v9fs_file_readn - read from a file * @filp: file pointer to read @@ -323,7 +477,8 @@ static const struct file_operations v9fs_cached_file_operations_dotl = { .write = v9fs_file_write, .open = v9fs_file_open, .release = v9fs_dir_release, - .lock = v9fs_file_lock, + .lock = v9fs_file_lock_dotl, + .flock = v9fs_file_flock_dotl, .mmap = generic_file_readonly_mmap, .fsync = v9fs_file_fsync_dotl, }; @@ -345,7 +500,8 @@ const struct file_operations v9fs_file_operations_dotl = { .write = v9fs_file_write, .open = v9fs_file_open, .release = v9fs_dir_release, - .lock = v9fs_file_lock, + .lock = v9fs_file_lock_dotl, + .flock = v9fs_file_flock_dotl, .mmap = generic_file_readonly_mmap, .fsync = v9fs_file_fsync_dotl, }; diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 55e96057f47f..1859a2560cc5 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -165,6 +165,8 @@ enum p9_msg_t { P9_RREADDIR, P9_TFSYNC = 50, P9_RFSYNC, + P9_TLOCK = 52, + P9_RLOCK, P9_TLINK = 70, P9_RLINK, P9_TMKDIR = 72, @@ -464,6 +466,32 @@ struct p9_iattr_dotl { u64 mtime_nsec; }; +#define P9_LOCK_SUCCESS 0 +#define P9_LOCK_BLOCKED 1 +#define P9_LOCK_ERROR 2 +#define P9_LOCK_GRACE 3 + +#define P9_LOCK_FLAGS_BLOCK 1 +#define P9_LOCK_FLAGS_RECLAIM 2 + +/* struct p9_flock: POSIX lock structure + * @type - type of lock + * @flags - lock flags + * @start - starting offset of the lock + * @length - number of bytes + * @proc_id - process id which wants to take lock + * @client_id - client id + */ + +struct p9_flock { + u8 type; + u32 flags; + u64 start; + u64 length; + u32 proc_id; + char *client_id; +}; + /* Structures for Protocol Operations */ struct p9_tstatfs { u32 fid; diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 8744e3ad4a07..d7dcb142e3bb 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -249,6 +249,7 @@ int p9_client_mknod_dotl(struct p9_fid *oldfid, char *name, int mode, dev_t rdev, gid_t gid, struct p9_qid *); int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode, gid_t gid, struct p9_qid *); +int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status); struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); void p9_client_cb(struct p9_client *c, struct p9_req_t *req); diff --git a/net/9p/client.c b/net/9p/client.c index 30c4a1b224fb..fbd2b195801c 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1803,3 +1803,36 @@ error: } EXPORT_SYMBOL(p9_client_mkdir_dotl); + +int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status) +{ + int err; + struct p9_client *clnt; + struct p9_req_t *req; + + err = 0; + clnt = fid->clnt; + P9_DPRINTK(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d " + "start %lld length %lld proc_id %d client_id %s\n", + fid->fid, flock->type, flock->flags, flock->start, + flock->length, flock->proc_id, flock->client_id); + + req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type, + flock->flags, flock->start, flock->length, + flock->proc_id, flock->client_id); + + if (IS_ERR(req)) + return PTR_ERR(req); + + err = p9pdu_readf(req->rc, clnt->proto_version, "b", status); + if (err) { + p9pdu_dump(1, req->rc); + goto error; + } + P9_DPRINTK(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status); +error: + p9_free_req(clnt, req); + return err; + +} +EXPORT_SYMBOL(p9_client_lock_dotl); -- cgit v1.2.3-59-g8ed1b From 1d769cd192fc8c4097b1e2cd41fdee6ba3d1b2af Mon Sep 17 00:00:00 2001 From: "M. Mohan Kumar" Date: Mon, 27 Sep 2010 12:22:13 +0530 Subject: 9p: Implement TGETLOCK Synopsis size[4] TGetlock tag[2] fid[4] getlock[n] size[4] RGetlock tag[2] getlock[n] Description TGetlock is used to test for the existence of byte range posix locks on a file identified by given fid. The reply contains getlock structure. If the lock could be placed it returns F_UNLCK in type field of getlock structure. Otherwise it returns the details of the conflicting locks in the getlock structure getlock structure: type[1] - Type of lock: F_RDLCK, F_WRLCK start[8] - Starting offset for lock length[8] - Number of bytes to check for the lock If length is 0, check for lock in all bytes starting at the location 'start' through to the end of file pid[4] - PID of the process that wants to take lock/owns the task in case of reply client[4] - Client id of the system that owns the process which has the conflicting lock Signed-off-by: M. Mohan Kumar Signed-off-by: Aneesh Kumar K.V Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_file.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ include/net/9p/9p.h | 18 ++++++++++++++++++ include/net/9p/client.h | 1 + net/9p/client.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+) (limited to 'include') diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 6f77abd23184..3a4352f23a98 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -211,6 +211,51 @@ out: return res; } +static int 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->fl_type != F_UNLCK) + return res; + + /* convert posix lock to p9 tgetlock args */ + memset(&glock, 0, sizeof(glock)); + glock.type = fl->fl_type; + glock.start = fl->fl_start; + if (fl->fl_end == OFFSET_MAX) + glock.length = 0; + else + glock.length = fl->fl_end - fl->fl_start + 1; + glock.proc_id = fl->fl_pid; + glock.client_id = utsname()->nodename; + + res = p9_client_getlock_dotl(fid, &glock); + if (res < 0) + return res; + if (glock.type != F_UNLCK) { + fl->fl_type = glock.type; + fl->fl_start = glock.start; + if (glock.length == 0) + fl->fl_end = OFFSET_MAX; + else + fl->fl_end = glock.start + glock.length - 1; + fl->fl_pid = glock.proc_id; + } else + fl->fl_type = F_UNLCK; + + return res; +} + /** * v9fs_file_lock_dotl - lock a file (or directory) * @filp: file to be locked @@ -238,6 +283,8 @@ static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl) if (IS_SETLK(cmd) || IS_SETLKW(cmd)) ret = v9fs_file_do_lock(filp, cmd, fl); + else if (IS_GETLK(cmd)) + ret = v9fs_file_getlock(filp, fl); else ret = -EINVAL; out_err: diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 1859a2560cc5..6367a71d84fc 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -167,6 +167,8 @@ enum p9_msg_t { P9_RFSYNC, P9_TLOCK = 52, P9_RLOCK, + P9_TGETLOCK = 54, + P9_RGETLOCK, P9_TLINK = 70, P9_RLINK, P9_TMKDIR = 72, @@ -492,6 +494,22 @@ struct p9_flock { char *client_id; }; +/* struct p9_getlock: getlock structure + * @type - type of lock + * @start - starting offset of the lock + * @length - number of bytes + * @proc_id - process id which wants to take lock + * @client_id - client id + */ + +struct p9_getlock { + u8 type; + u64 start; + u64 length; + u32 proc_id; + char *client_id; +}; + /* Structures for Protocol Operations */ struct p9_tstatfs { u32 fid; diff --git a/include/net/9p/client.h b/include/net/9p/client.h index d7dcb142e3bb..127c9f2a9cb8 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -250,6 +250,7 @@ int p9_client_mknod_dotl(struct p9_fid *oldfid, char *name, int mode, int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode, gid_t gid, struct p9_qid *); int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status); +int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *fl); struct p9_req_t *p9_tag_lookup(struct p9_client *, u16); void p9_client_cb(struct p9_client *c, struct p9_req_t *req); diff --git a/net/9p/client.c b/net/9p/client.c index fbd2b195801c..fc1b0579016a 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1836,3 +1836,37 @@ error: } EXPORT_SYMBOL(p9_client_lock_dotl); + +int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock) +{ + int err; + struct p9_client *clnt; + struct p9_req_t *req; + + err = 0; + clnt = fid->clnt; + P9_DPRINTK(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld " + "length %lld proc_id %d client_id %s\n", fid->fid, glock->type, + glock->start, glock->length, glock->proc_id, glock->client_id); + + req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid, glock->type, + glock->start, glock->length, glock->proc_id, glock->client_id); + + if (IS_ERR(req)) + return PTR_ERR(req); + + err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type, + &glock->start, &glock->length, &glock->proc_id, + &glock->client_id); + if (err) { + p9pdu_dump(1, req->rc); + goto error; + } + P9_DPRINTK(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld " + "proc_id %d client_id %s\n", glock->type, glock->start, + glock->length, glock->proc_id, glock->client_id); +error: + p9_free_req(clnt, req); + return err; +} +EXPORT_SYMBOL(p9_client_getlock_dotl); -- cgit v1.2.3-59-g8ed1b From 368c09d2a303c39e9f37193b23e945e6754cf0a7 Mon Sep 17 00:00:00 2001 From: "M. Mohan Kumar" Date: Mon, 27 Sep 2010 14:17:24 +0530 Subject: 9p: Use V9FS_MAGIC in statfs Use V9FS_MAGIC as the file system type while filling kernel statfs strucutre instead of using host file system magic number. Also move the definition of V9FS_MAGIC from v9fs.h to standard magic.h file. Signed-off-by: M. Mohan Kumar Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/v9fs.h | 2 -- fs/9p/vfs_super.c | 3 ++- include/linux/magic.h | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 8bb7792afe2e..cb6396855e2d 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -117,8 +117,6 @@ void v9fs_session_close(struct v9fs_session_info *v9ses); void v9fs_session_cancel(struct v9fs_session_info *v9ses); void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses); -#define V9FS_MAGIC 0x01021997 - /* other default globals */ #define V9FS_PORT 564 #define V9FS_DEFUSER "nobody" diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 174643f4f901..48d4215c60a8 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -256,7 +257,7 @@ static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) if (v9fs_proto_dotl(v9ses)) { res = p9_client_statfs(fid, &rs); if (res == 0) { - buf->f_type = rs.type; + buf->f_type = V9FS_MAGIC; buf->f_bsize = rs.bsize; buf->f_blocks = rs.blocks; buf->f_bfree = rs.bfree; diff --git a/include/linux/magic.h b/include/linux/magic.h index eb9800f05782..ff690d05f129 100644 --- a/include/linux/magic.h +++ b/include/linux/magic.h @@ -57,5 +57,6 @@ #define DEVPTS_SUPER_MAGIC 0x1cd1 #define SOCKFS_MAGIC 0x534F434B +#define V9FS_MAGIC 0x01021997 #endif /* __LINUX_MAGIC_H__ */ -- cgit v1.2.3-59-g8ed1b From 329176cc2c50e63c580ddaabb385876db5af1360 Mon Sep 17 00:00:00 2001 From: "M. Mohan Kumar" Date: Tue, 28 Sep 2010 19:59:25 +0530 Subject: 9p: Implement TREADLINK operation for 9p2000.L Synopsis size[4] TReadlink tag[2] fid[4] size[4] RReadlink tag[2] target[s] Description Readlink is used to return the contents of the symoblic link referred by fid. Contents of symboic link is returned as a response. target[s] - Contents of the symbolic link referred by fid. Signed-off-by: M. Mohan Kumar Reviewed-by: Aneesh Kumar K.V Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_inode.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++--- include/net/9p/9p.h | 2 ++ include/net/9p/client.h | 1 + net/9p/client.c | 26 +++++++++++++++++++++ 4 files changed, 86 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 68f02973c338..88419073c654 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1527,7 +1527,7 @@ static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) if (IS_ERR(fid)) return PTR_ERR(fid); - if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) + if (!v9fs_proto_dotu(v9ses)) return -EBADF; st = p9_client_stat(fid); @@ -1995,6 +1995,60 @@ error: return err; } +static int +v9fs_vfs_readlink_dotl(struct dentry *dentry, char *buffer, int buflen) +{ + int retval; + struct p9_fid *fid; + char *target = NULL; + + P9_DPRINTK(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); + retval = -EPERM; + fid = v9fs_fid_lookup(dentry); + if (IS_ERR(fid)) + return PTR_ERR(fid); + + retval = p9_client_readlink(fid, &target); + if (retval < 0) + return retval; + + strncpy(buffer, target, buflen); + P9_DPRINTK(P9_DEBUG_VFS, "%s -> %s\n", dentry->d_name.name, buffer); + + retval = strnlen(buffer, buflen); + return retval; +} + +/** + * v9fs_vfs_follow_link_dotl - follow a symlink path + * @dentry: dentry for symlink + * @nd: nameidata + * + */ + +static void * +v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) +{ + int len = 0; + char *link = __getname(); + + P9_DPRINTK(P9_DEBUG_VFS, "%s n", dentry->d_name.name); + + if (!link) + link = ERR_PTR(-ENOMEM); + else { + len = v9fs_vfs_readlink_dotl(dentry, link, PATH_MAX); + if (len < 0) { + __putname(link); + link = ERR_PTR(len); + } else + link[min(len, PATH_MAX-1)] = 0; + } + nd_set_link(nd, link); + + return NULL; +} + static const struct inode_operations v9fs_dir_inode_operations_dotu = { .create = v9fs_vfs_create, .lookup = v9fs_vfs_lookup, @@ -2064,8 +2118,8 @@ static const struct inode_operations v9fs_symlink_inode_operations = { }; static const struct inode_operations v9fs_symlink_inode_operations_dotl = { - .readlink = generic_readlink, - .follow_link = v9fs_vfs_follow_link, + .readlink = v9fs_vfs_readlink_dotl, + .follow_link = v9fs_vfs_follow_link_dotl, .put_link = v9fs_vfs_put_link, .getattr = v9fs_vfs_getattr_dotl, .setattr = v9fs_vfs_setattr_dotl, diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 6367a71d84fc..071fd7a8d781 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -153,6 +153,8 @@ enum p9_msg_t { P9_RMKNOD, P9_TRENAME = 20, P9_RRENAME, + P9_TREADLINK = 22, + P9_RREADLINK, P9_TGETATTR = 24, P9_RGETATTR, P9_TSETATTR = 26, diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 127c9f2a9cb8..335b088e7672 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -262,5 +262,6 @@ int p9_is_proto_dotu(struct p9_client *clnt); int p9_is_proto_dotl(struct p9_client *clnt); struct p9_fid *p9_client_xattrwalk(struct p9_fid *, const char *, u64 *); int p9_client_xattrcreate(struct p9_fid *, const char *, u64, int); +int p9_client_readlink(struct p9_fid *fid, char **target); #endif /* NET_9P_CLIENT_H */ diff --git a/net/9p/client.c b/net/9p/client.c index fc1b0579016a..2bc99e9031e7 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1870,3 +1870,29 @@ error: return err; } EXPORT_SYMBOL(p9_client_getlock_dotl); + +int p9_client_readlink(struct p9_fid *fid, char **target) +{ + int err; + struct p9_client *clnt; + struct p9_req_t *req; + + err = 0; + clnt = fid->clnt; + P9_DPRINTK(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid); + + req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid); + if (IS_ERR(req)) + return PTR_ERR(req); + + err = p9pdu_readf(req->rc, clnt->proto_version, "s", target); + if (err) { + p9pdu_dump(1, req->rc); + goto error; + } + P9_DPRINTK(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target); +error: + p9_free_req(clnt, req); + return err; +} +EXPORT_SYMBOL(p9_client_readlink); -- cgit v1.2.3-59-g8ed1b From b165d60145b717261a0234f989c442c2b68b6ec0 Mon Sep 17 00:00:00 2001 From: "Venkateswararao Jujjuri (JV)" Date: Fri, 22 Oct 2010 10:13:12 -0700 Subject: 9p: Add datasync to client side TFSYNC/RFSYNC for dotl SYNOPSIS size[4] Tfsync tag[2] fid[4] datasync[4] size[4] Rfsync tag[2] DESCRIPTION The Tfsync transaction transfers ("flushes") all modified in-core data of file identified by fid to the disk device (or other permanent storage device) where that file resides. If datasync flag is specified data will be fleshed but does not flush modified metadata unless that metadata is needed in order to allow a subsequent data retrieval to be correctly handled. Signed-off-by: Venkateswararao Jujjuri Signed-off-by: Eric Van Hensbergen --- fs/9p/v9fs_vfs.h | 1 + fs/9p/vfs_dir.c | 1 + fs/9p/vfs_file.c | 4 ++-- include/net/9p/client.h | 2 +- net/9p/client.c | 7 ++++--- 5 files changed, 9 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h index d26db1932f7a..bab0eac873f4 100644 --- a/fs/9p/v9fs_vfs.h +++ b/fs/9p/v9fs_vfs.h @@ -65,5 +65,6 @@ int v9fs_uflags2omode(int uflags, int extended); ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64); void v9fs_blank_wstat(struct p9_wstat *wstat); int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); +int v9fs_file_fsync_dotl(struct file *filp, int datasync); #define P9_LOCK_TIMEOUT (30*HZ) diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 170f5bb8ebe0..b84ebe8cefed 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -315,4 +315,5 @@ const struct file_operations v9fs_dir_operations_dotl = { .readdir = v9fs_dir_readdir_dotl, .open = v9fs_file_open, .release = v9fs_dir_release, + .fsync = v9fs_file_fsync_dotl, }; diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 3a4352f23a98..240c30674396 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -491,7 +491,7 @@ static int v9fs_file_fsync(struct file *filp, int datasync) return retval; } -static int v9fs_file_fsync_dotl(struct file *filp, int datasync) +int v9fs_file_fsync_dotl(struct file *filp, int datasync) { struct p9_fid *fid; int retval; @@ -501,7 +501,7 @@ static int v9fs_file_fsync_dotl(struct file *filp, int datasync) fid = filp->private_data; - retval = p9_client_fsync(fid); + retval = p9_client_fsync(fid, datasync); return retval; } diff --git a/include/net/9p/client.h b/include/net/9p/client.h index 335b088e7672..83ba6a4d58a3 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -229,7 +229,7 @@ int p9_client_symlink(struct p9_fid *fid, char *name, char *symname, gid_t gid, int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode, gid_t gid, struct p9_qid *qid); int p9_client_clunk(struct p9_fid *fid); -int p9_client_fsync(struct p9_fid *fid); +int p9_client_fsync(struct p9_fid *fid, int datasync); int p9_client_remove(struct p9_fid *fid); int p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, u32 count); diff --git a/net/9p/client.c b/net/9p/client.c index e3cfdff37327..8df80fb86f23 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -1165,17 +1165,18 @@ int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname) } EXPORT_SYMBOL(p9_client_link); -int p9_client_fsync(struct p9_fid *fid) +int p9_client_fsync(struct p9_fid *fid, int datasync) { int err; struct p9_client *clnt; struct p9_req_t *req; - P9_DPRINTK(P9_DEBUG_9P, ">>> TFSYNC fid %d\n", fid->fid); + P9_DPRINTK(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n", + fid->fid, datasync); err = 0; clnt = fid->clnt; - req = p9_client_rpc(clnt, P9_TFSYNC, "d", fid->fid); + req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync); if (IS_ERR(req)) { err = PTR_ERR(req); goto error; -- cgit v1.2.3-59-g8ed1b