Bug#592557: Patch
Hi,
Attached is a working patch for 2.6.26-24.
Regards,
Frodo
--
Frodo Looijaard <frodo@frodo.looijaard.name> (See http://frodo.looijaard.name/)
Defenestration n. (formal or joc.):
The act of removing Windows from your computer in disgust, usually followed
by the installation of Linux or some other Unix-like operating system.
diff -Nurp linux-source-2.6.26.orig/fs/nfs/dir.c linux-source-2.6.26/fs/nfs/dir.c
--- linux-source-2.6.26.orig/fs/nfs/dir.c 2010-08-11 10:07:24.000000000 +0200
+++ linux-source-2.6.26/fs/nfs/dir.c 2010-08-11 13:23:12.000000000 +0200
@@ -765,6 +765,7 @@ static int nfs_lookup_revalidate(struct
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
+ struct rpc_groups fsg;
parent = dget_parent(dentry);
lock_kernel();
@@ -795,7 +796,9 @@ static int nfs_lookup_revalidate(struct
if (NFS_STALE(inode))
goto out_bad;
- error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+ fsg.ngroups = 1;
+ fsg.groups[0] = dir->i_gid;
+ error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr, &fsg);
if (error)
goto out_bad;
if (nfs_compare_fh(NFS_FH(inode), &fhandle))
@@ -891,6 +894,7 @@ static struct dentry *nfs_lookup(struct
int error;
struct nfs_fh fhandle;
struct nfs_fattr fattr;
+ struct rpc_groups fsg;
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
@@ -918,7 +922,9 @@ static struct dentry *nfs_lookup(struct
parent = dentry->d_parent;
/* Protect against concurrent sillydeletes */
nfs_block_sillyrename(parent);
- error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr);
+ fsg.ngroups = 1;
+ fsg.groups[0] = dir->i_gid;
+ error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, &fhandle, &fattr, &fsg);
if (error == -ENOENT)
goto no_entry;
if (error < 0) {
@@ -1158,7 +1164,7 @@ out_renew:
* Code common to create, mkdir, and mknod.
*/
int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr)
+ struct nfs_fattr *fattr, struct rpc_groups *fsg)
{
struct dentry *parent = dget_parent(dentry);
struct inode *dir = parent->d_inode;
@@ -1171,7 +1177,7 @@ int nfs_instantiate(struct dentry *dentr
if (dentry->d_inode)
goto out;
if (fhandle->size == 0) {
- error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
+ error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, fsg);
if (error)
goto out_error;
}
@@ -1208,6 +1214,7 @@ static int nfs_create(struct inode *dir,
struct iattr attr;
int error;
int open_flags = 0;
+ struct rpc_groups fsg = { 1, { dir->i_gid } };
dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1219,7 +1226,7 @@ static int nfs_create(struct inode *dir,
open_flags = nd->intent.open.flags;
lock_kernel();
- error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd);
+ error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd, &fsg);
if (error != 0)
goto out_err;
unlock_kernel();
@@ -1238,6 +1245,7 @@ nfs_mknod(struct inode *dir, struct dent
{
struct iattr attr;
int status;
+ struct rpc_groups fsg = { 1, { dir->i_gid } };
dfprintk(VFS, "NFS: mknod(%s/%ld), %s\n",
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1249,7 +1257,7 @@ nfs_mknod(struct inode *dir, struct dent
attr.ia_valid = ATTR_MODE;
lock_kernel();
- status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev);
+ status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev, &fsg);
if (status != 0)
goto out_err;
unlock_kernel();
@@ -1267,6 +1275,7 @@ static int nfs_mkdir(struct inode *dir,
{
struct iattr attr;
int error;
+ struct rpc_groups fsg = { 1, { dir->i_gid } };
dfprintk(VFS, "NFS: mkdir(%s/%ld), %s\n",
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1275,7 +1284,7 @@ static int nfs_mkdir(struct inode *dir,
attr.ia_mode = mode | S_IFDIR;
lock_kernel();
- error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr);
+ error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr, &fsg);
if (error != 0)
goto out_err;
unlock_kernel();
@@ -1295,12 +1304,13 @@ static void nfs_dentry_handle_enoent(str
static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int error;
+ struct rpc_groups fsg = { 1, { dir->i_gid } };
dfprintk(VFS, "NFS: rmdir(%s/%ld), %s\n",
dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
lock_kernel();
- error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name);
+ error = NFS_PROTO(dir)->rmdir(dir, &dentry->d_name, &fsg);
/* Ensure the VFS deletes this inode */
if (error == 0 && dentry->d_inode != NULL)
clear_nlink(dentry->d_inode);
@@ -1321,6 +1331,7 @@ static int nfs_sillyrename(struct inode
struct qstr qsilly;
struct dentry *sdentry;
int error = -EIO;
+ struct rpc_groups fsg = { 1, { dir->i_gid } };
dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
dentry->d_parent->d_name.name, dentry->d_name.name,
@@ -1365,11 +1376,11 @@ static int nfs_sillyrename(struct inode
qsilly.len = strlen(silly);
if (dentry->d_inode) {
error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
- dir, &qsilly);
+ dir, &qsilly, &fsg);
nfs_mark_for_revalidate(dentry->d_inode);
} else
error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
- dir, &qsilly);
+ dir, &qsilly, &fsg);
if (!error) {
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
d_move(dentry, sdentry);
@@ -1392,6 +1403,7 @@ static int nfs_safe_remove(struct dentry
{
struct inode *dir = dentry->d_parent->d_inode;
struct inode *inode = dentry->d_inode;
+ struct rpc_groups fsg = { 1, { dir->i_gid } };
int error = -EBUSY;
dfprintk(VFS, "NFS: safe_remove(%s/%s)\n",
@@ -1405,13 +1417,13 @@ static int nfs_safe_remove(struct dentry
if (inode != NULL) {
nfs_inode_return_delegation(inode);
- error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+ error = NFS_PROTO(dir)->remove(dir, &dentry->d_name, &fsg);
/* The VFS may want to delete this inode */
if (error == 0)
drop_nlink(inode);
nfs_mark_for_revalidate(inode);
} else
- error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
+ error = NFS_PROTO(dir)->remove(dir, &dentry->d_name, &fsg);
if (error == -ENOENT)
nfs_dentry_handle_enoent(dentry);
out:
@@ -1481,6 +1493,7 @@ static int nfs_symlink(struct inode *dir
struct iattr attr;
unsigned int pathlen = strlen(symname);
int error;
+ struct rpc_groups fsg = { 1, { dir->i_gid } };
dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s)\n", dir->i_sb->s_id,
dir->i_ino, dentry->d_name.name, symname);
@@ -1505,7 +1518,7 @@ static int nfs_symlink(struct inode *dir
memset(kaddr + pathlen, 0, PAGE_SIZE - pathlen);
kunmap_atomic(kaddr, KM_USER0);
- error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr);
+ error = NFS_PROTO(dir)->symlink(dir, dentry, page, pathlen, &attr, &fsg);
if (error != 0) {
dfprintk(VFS, "NFS: symlink(%s/%ld, %s, %s) error %d\n",
dir->i_sb->s_id, dir->i_ino,
@@ -1538,6 +1551,7 @@ static int
nfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
{
struct inode *inode = old_dentry->d_inode;
+ struct rpc_groups fsg = { 1, { dir->i_gid } };
int error;
dfprintk(VFS, "NFS: link(%s/%s -> %s/%s)\n",
@@ -1546,7 +1560,7 @@ nfs_link(struct dentry *old_dentry, stru
lock_kernel();
d_drop(dentry);
- error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name);
+ error = NFS_PROTO(dir)->link(inode, dir, &dentry->d_name, &fsg);
if (error == 0) {
atomic_inc(&inode->i_count);
d_add(dentry, inode);
@@ -1585,6 +1599,14 @@ static int nfs_rename(struct inode *old_
struct inode *old_inode = old_dentry->d_inode;
struct inode *new_inode = new_dentry->d_inode;
struct dentry *dentry = NULL, *rehash = NULL;
+ struct rpc_groups fsg = {
+ .ngroups = 3,
+ .groups = {
+ old_dir->i_gid,
+ new_dir->i_gid, /* old_dir != new_dir */
+ old_inode->i_gid /* reparent a dir */
+ }
+ };
int error = -EBUSY;
/*
@@ -1654,7 +1676,7 @@ go_ahead:
}
error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name,
- new_dir, &new_dentry->d_name);
+ new_dir, &new_dentry->d_name, &fsg);
nfs_mark_for_revalidate(old_inode);
out:
if (rehash)
@@ -1902,6 +1924,8 @@ static int nfs_do_access(struct inode *i
cache.cred = cred;
cache.jiffies = jiffies;
status = NFS_PROTO(inode)->access(inode, &cache);
+ dfprintk(VFS, "NFS: access()=%d for ino %lu, cred %p, mask 0x%x->0x%x\n",
+ status, inode->i_ino, cred, mask, cache.mask);
if (status != 0) {
if (status == -ESTALE) {
nfs_zap_caches(inode);
@@ -1974,7 +1998,12 @@ force_lookup:
if (!NFS_PROTO(inode)->access)
goto out_notsup;
- cred = rpc_lookup_cred();
+ if (NFS_PROTO(inode)->version > 3)
+ cred = rpc_lookup_cred(NULL);
+ else {
+ struct rpc_groups fsg = { 1, { inode->i_gid } };
+ cred = rpc_lookup_cred(&fsg);
+ }
if (!IS_ERR(cred)) {
res = nfs_do_access(inode, cred, mask);
put_rpccred(cred);
diff -Nurp linux-source-2.6.26.orig/fs/nfs/inode.c linux-source-2.6.26/fs/nfs/inode.c
--- linux-source-2.6.26.orig/fs/nfs/inode.c 2010-08-11 10:07:24.000000000 +0200
+++ linux-source-2.6.26/fs/nfs/inode.c 2010-08-11 13:23:12.000000000 +0200
@@ -352,6 +352,7 @@ nfs_setattr(struct dentry *dentry, struc
{
struct inode *inode = dentry->d_inode;
struct nfs_fattr fattr;
+ struct rpc_groups fsg;
int error;
nfs_inc_stats(inode, NFSIOS_VFSSETATTR);
@@ -381,7 +382,11 @@ nfs_setattr(struct dentry *dentry, struc
*/
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
nfs_inode_return_delegation(inode);
- error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);
+ fsg.ngroups = 0;
+ fsg.groups[fsg.ngroups++] = inode->i_gid; /* ATTR_SIZE */
+ if (attr->ia_valid & ATTR_GID)
+ fsg.groups[fsg.ngroups++] = attr->ia_gid;
+ error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr, &fsg);
if (error == 0)
nfs_refresh_inode(inode, &fattr);
unlock_kernel();
@@ -611,7 +616,12 @@ int nfs_open(struct inode *inode, struct
struct nfs_open_context *ctx;
struct rpc_cred *cred;
- cred = rpc_lookup_cred();
+ if (NFS_PROTO(inode)->version > 3)
+ cred = rpc_lookup_cred(NULL);
+ else {
+ struct rpc_groups fsg = { 1, { inode->i_gid } };
+ cred = rpc_lookup_cred(&fsg);
+ }
if (IS_ERR(cred))
return PTR_ERR(cred);
ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.dentry, cred);
diff -Nurp linux-source-2.6.26.orig/fs/nfs/namespace.c linux-source-2.6.26/fs/nfs/namespace.c
--- linux-source-2.6.26.orig/fs/nfs/namespace.c 2010-08-11 10:07:24.000000000 +0200
+++ linux-source-2.6.26/fs/nfs/namespace.c 2010-08-11 13:23:12.000000000 +0200
@@ -101,6 +101,7 @@ static void * nfs_follow_mountpoint(stru
struct dentry *parent;
struct nfs_fh fh;
struct nfs_fattr fattr;
+ struct rpc_groups fsg;
int err;
dprintk("--> nfs_follow_mountpoint()\n");
@@ -112,9 +113,11 @@ static void * nfs_follow_mountpoint(stru
/* Look it up again */
parent = dget_parent(nd->path.dentry);
+ fsg.ngroups = 1;
+ fsg.groups[0] = parent->d_inode->i_gid;
err = server->nfs_client->rpc_ops->lookup(parent->d_inode,
&nd->path.dentry->d_name,
- &fh, &fattr);
+ &fh, &fattr, &fsg);
dput(parent);
if (err != 0)
goto out_err;
diff -Nurp linux-source-2.6.26.orig/fs/nfs/nfs3proc.c linux-source-2.6.26/fs/nfs/nfs3proc.c
--- linux-source-2.6.26.orig/fs/nfs/nfs3proc.c 2010-08-11 10:07:24.000000000 +0200
+++ linux-source-2.6.26/fs/nfs/nfs3proc.c 2010-08-11 13:23:12.000000000 +0200
@@ -25,11 +25,19 @@
/* A wrapper to handle the EJUKEBOX error message */
static int
-nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags)
+nfs3_rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp,
+ struct rpc_cred *cred, int flags)
{
+ struct rpc_message msg = {
+ .rpc_proc = &nfs3_procedures[proc],
+ .rpc_argp = argp,
+ .rpc_resp = resp,
+ .rpc_cred = cred,
+ };
int res;
+
do {
- res = rpc_call_sync(clnt, msg, flags);
+ res = rpc_call_sync(clnt, &msg, flags);
if (res != -EJUKEBOX)
break;
schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME);
@@ -38,7 +46,20 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt,
return res;
}
-#define rpc_call_sync(clnt, msg, flags) nfs3_rpc_wrapper(clnt, msg, flags)
+static int
+nfs3_rpc(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp,
+ struct rpc_groups *fsg)
+{
+ struct rpc_cred *cred;
+ int res;
+
+ cred = rpcauth_lookupcred(clnt->cl_auth, fsg, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
+ res = nfs3_rpc_call(clnt, proc, argp, resp, cred, 0);
+ put_rpccred(cred);
+ return res;
+}
static int
nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode)
@@ -56,21 +77,14 @@ static int
do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
- .rpc_argp = fhandle,
- .rpc_resp = info,
- };
int status;
dprintk("%s: call fsinfo\n", __func__);
nfs_fattr_init(info->fattr);
- status = rpc_call_sync(client, &msg, 0);
+ status = nfs3_rpc(client, NFS3PROC_FSINFO, fhandle, info, NULL);
dprintk("%s: reply fsinfo: %d\n", __func__, status);
if (!(info->fattr->valid & NFS_ATTR_FATTR)) {
- msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
- msg.rpc_resp = info->fattr;
- status = rpc_call_sync(client, &msg, 0);
+ status = nfs3_rpc(client, NFS3PROC_GETATTR, fhandle, info->fattr, NULL);
dprintk("%s: reply getattr: %d\n", __func__, status);
}
return status;
@@ -98,39 +112,29 @@ static int
nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR],
- .rpc_argp = fhandle,
- .rpc_resp = fattr,
- };
int status;
dprintk("NFS call getattr\n");
nfs_fattr_init(fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs3_rpc(server->client, NFS3PROC_GETATTR, fhandle, fattr, NULL);
dprintk("NFS reply getattr: %d\n", status);
return status;
}
static int
nfs3_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
- struct iattr *sattr)
+ struct iattr *sattr, struct rpc_groups *fsg)
{
struct inode *inode = dentry->d_inode;
struct nfs3_sattrargs arg = {
.fh = NFS_FH(inode),
.sattr = sattr,
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_SETATTR],
- .rpc_argp = &arg,
- .rpc_resp = fattr,
- };
int status;
dprintk("NFS call setattr\n");
nfs_fattr_init(fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(inode), NFS3PROC_SETATTR, &arg, fattr, fsg);
if (status == 0)
nfs_setattr_update_inode(inode, sattr);
dprintk("NFS reply setattr: %d\n", status);
@@ -139,7 +143,8 @@ nfs3_proc_setattr(struct dentry *dentry,
static int
nfs3_proc_lookup(struct inode *dir, struct qstr *name,
- struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+ struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+ struct rpc_groups *fsg)
{
struct nfs_fattr dir_attr;
struct nfs3_diropargs arg = {
@@ -152,23 +157,16 @@ nfs3_proc_lookup(struct inode *dir, stru
.fh = fhandle,
.fattr = fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_LOOKUP],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
dprintk("NFS call lookup %s\n", name->name);
nfs_fattr_init(&dir_attr);
nfs_fattr_init(fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_LOOKUP, &arg, &res, fsg);
nfs_refresh_inode(dir, &dir_attr);
if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
- msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
- msg.rpc_argp = fhandle;
- msg.rpc_resp = fattr;
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_GETATTR,
+ fhandle, fattr, NULL);
}
dprintk("NFS reply lookup: %d\n", status);
return status;
@@ -183,12 +181,6 @@ static int nfs3_proc_access(struct inode
struct nfs3_accessres res = {
.fattr = &fattr,
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_ACCESS],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- .rpc_cred = entry->cred,
- };
int mode = entry->mask;
int status;
@@ -208,7 +200,8 @@ static int nfs3_proc_access(struct inode
arg.access |= NFS3_ACCESS_EXECUTE;
}
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = nfs3_rpc_call(NFS_CLIENT(inode), NFS3PROC_ACCESS,
+ &arg, &res, entry->cred, 0);
nfs_refresh_inode(inode, &fattr);
if (status == 0) {
entry->mask = 0;
@@ -233,16 +226,11 @@ static int nfs3_proc_readlink(struct ino
.pglen = pglen,
.pages = &page
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_READLINK],
- .rpc_argp = &args,
- .rpc_resp = &fattr,
- };
int status;
dprintk("NFS call readlink\n");
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(inode), NFS3PROC_READLINK, &args, &fattr, NULL);
nfs_refresh_inode(inode, &fattr);
dprintk("NFS reply readlink: %d\n", status);
return status;
@@ -254,7 +242,7 @@ static int nfs3_proc_readlink(struct ino
*/
static int
nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
- int flags, struct nameidata *nd)
+ int flags, struct nameidata *nd, struct rpc_groups *fsg)
{
struct nfs_fh fhandle;
struct nfs_fattr fattr;
@@ -270,11 +258,6 @@ nfs3_proc_create(struct inode *dir, stru
.fh = &fhandle,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_CREATE],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
mode_t mode = sattr->ia_mode;
int status;
@@ -291,7 +274,7 @@ nfs3_proc_create(struct inode *dir, stru
again:
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_CREATE, &arg, &res, fsg);
nfs_refresh_inode(dir, &dir_attr);
/* If the server doesn't support the exclusive creation semantics,
@@ -313,7 +296,7 @@ again:
}
if (status == 0)
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ status = nfs_instantiate(dentry, &fhandle, &fattr, fsg);
if (status != 0)
goto out;
@@ -330,7 +313,7 @@ again:
/* Note: we could use a guarded setattr here, but I'm
* not sure this buys us anything (and I'd have
* to revamp the NFSv3 XDR code) */
- status = nfs3_proc_setattr(dentry, &fattr, sattr);
+ status = nfs3_proc_setattr(dentry, &fattr, sattr, NULL);
nfs_post_op_update_inode(dentry->d_inode, &fattr);
dprintk("NFS reply setattr (post-create): %d\n", status);
}
@@ -343,7 +326,7 @@ out:
}
static int
-nfs3_proc_remove(struct inode *dir, struct qstr *name)
+nfs3_proc_remove(struct inode *dir, struct qstr *name, struct rpc_groups *fsg)
{
struct nfs_removeargs arg = {
.fh = NFS_FH(dir),
@@ -351,16 +334,11 @@ nfs3_proc_remove(struct inode *dir, stru
.name.name = name->name,
};
struct nfs_removeres res;
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
dprintk("NFS call remove %s\n", name->name);
nfs_fattr_init(&res.dir_attr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_REMOVE, &arg, &res, fsg);
nfs_post_op_update_inode(dir, &res.dir_attr);
dprintk("NFS reply remove: %d\n", status);
return status;
@@ -385,7 +363,8 @@ nfs3_proc_unlink_done(struct rpc_task *t
static int
nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
- struct inode *new_dir, struct qstr *new_name)
+ struct inode *new_dir, struct qstr *new_name,
+ struct rpc_groups *fsg)
{
struct nfs_fattr old_dir_attr, new_dir_attr;
struct nfs3_renameargs arg = {
@@ -400,17 +379,12 @@ nfs3_proc_rename(struct inode *old_dir,
.fromattr = &old_dir_attr,
.toattr = &new_dir_attr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_RENAME],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name);
nfs_fattr_init(&old_dir_attr);
nfs_fattr_init(&new_dir_attr);
- status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(old_dir), NFS3PROC_RENAME, &arg, &res, fsg);
nfs_post_op_update_inode(old_dir, &old_dir_attr);
nfs_post_op_update_inode(new_dir, &new_dir_attr);
dprintk("NFS reply rename: %d\n", status);
@@ -418,7 +392,8 @@ nfs3_proc_rename(struct inode *old_dir,
}
static int
-nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name,
+ struct rpc_groups *fsg)
{
struct nfs_fattr dir_attr, fattr;
struct nfs3_linkargs arg = {
@@ -431,17 +406,12 @@ nfs3_proc_link(struct inode *inode, stru
.dir_attr = &dir_attr,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_LINK],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
dprintk("NFS call link %s\n", name->name);
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(inode), NFS3PROC_LINK, &arg, &res, fsg);
nfs_post_op_update_inode(dir, &dir_attr);
nfs_post_op_update_inode(inode, &fattr);
dprintk("NFS reply link: %d\n", status);
@@ -450,7 +420,7 @@ nfs3_proc_link(struct inode *inode, stru
static int
nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
- unsigned int len, struct iattr *sattr)
+ unsigned int len, struct iattr *sattr, struct rpc_groups *fsg)
{
struct nfs_fh fhandle;
struct nfs_fattr fattr, dir_attr;
@@ -467,11 +437,6 @@ nfs3_proc_symlink(struct inode *dir, str
.fh = &fhandle,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
if (len > NFS3_MAXPATHLEN)
@@ -481,18 +446,19 @@ nfs3_proc_symlink(struct inode *dir, str
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_SYMLINK, &arg, &res, fsg);
nfs_post_op_update_inode(dir, &dir_attr);
if (status != 0)
goto out;
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ status = nfs_instantiate(dentry, &fhandle, &fattr, fsg);
out:
dprintk("NFS reply symlink: %d\n", status);
return status;
}
static int
-nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
+nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ struct rpc_groups *fsg)
{
struct nfs_fh fhandle;
struct nfs_fattr fattr, dir_attr;
@@ -507,11 +473,6 @@ nfs3_proc_mkdir(struct inode *dir, struc
.fh = &fhandle,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int mode = sattr->ia_mode;
int status;
@@ -521,11 +482,11 @@ nfs3_proc_mkdir(struct inode *dir, struc
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, fsg);
nfs_post_op_update_inode(dir, &dir_attr);
if (status != 0)
goto out;
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ status = nfs_instantiate(dentry, &fhandle, &fattr, fsg);
if (status != 0)
goto out;
status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
@@ -535,7 +496,7 @@ out:
}
static int
-nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
+nfs3_proc_rmdir(struct inode *dir, struct qstr *name, struct rpc_groups *fsg)
{
struct nfs_fattr dir_attr;
struct nfs3_diropargs arg = {
@@ -543,16 +504,11 @@ nfs3_proc_rmdir(struct inode *dir, struc
.name = name->name,
.len = name->len
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_RMDIR],
- .rpc_argp = &arg,
- .rpc_resp = &dir_attr,
- };
int status;
dprintk("NFS call rmdir %s\n", name->name);
nfs_fattr_init(&dir_attr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_RMDIR, &arg, &dir_attr, fsg);
nfs_post_op_update_inode(dir, &dir_attr);
dprintk("NFS reply rmdir: %d\n", status);
return status;
@@ -587,22 +543,17 @@ nfs3_proc_readdir(struct dentry *dentry,
.verf = verf,
.plus = plus
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_READDIR],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- .rpc_cred = cred
- };
int status;
+ u32 proc = NFS3PROC_READDIR;
if (plus)
- msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS];
+ proc = NFS3PROC_READDIRPLUS;
dprintk("NFS call readdir%s %d\n",
plus? "plus" : "", (unsigned int) cookie);
nfs_fattr_init(&dir_attr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs3_rpc_call(NFS_CLIENT(dir), proc, &arg, &res, cred, 0);
nfs_invalidate_atime(dir);
@@ -613,7 +564,7 @@ nfs3_proc_readdir(struct dentry *dentry,
static int
nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
- dev_t rdev)
+ dev_t rdev, struct rpc_groups *fsg)
{
struct nfs_fh fh;
struct nfs_fattr fattr, dir_attr;
@@ -629,11 +580,6 @@ nfs3_proc_mknod(struct inode *dir, struc
.fh = &fh,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
mode_t mode = sattr->ia_mode;
int status;
@@ -652,11 +598,11 @@ nfs3_proc_mknod(struct inode *dir, struc
nfs_fattr_init(&dir_attr);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs3_rpc(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, fsg);
nfs_post_op_update_inode(dir, &dir_attr);
if (status != 0)
goto out;
- status = nfs_instantiate(dentry, &fh, &fattr);
+ status = nfs_instantiate(dentry, &fh, &fattr, fsg);
if (status != 0)
goto out;
status = nfs3_proc_set_default_acl(dir, dentry->d_inode, mode);
@@ -669,16 +615,11 @@ static int
nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fsstat *stat)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_FSSTAT],
- .rpc_argp = fhandle,
- .rpc_resp = stat,
- };
int status;
dprintk("NFS call fsstat\n");
nfs_fattr_init(stat->fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs3_rpc(server->client, NFS3PROC_FSSTAT, fhandle, stat, NULL);
dprintk("NFS reply statfs: %d\n", status);
return status;
}
@@ -687,16 +628,11 @@ static int
do_proc_fsinfo(struct rpc_clnt *client, struct nfs_fh *fhandle,
struct nfs_fsinfo *info)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_FSINFO],
- .rpc_argp = fhandle,
- .rpc_resp = info,
- };
int status;
dprintk("NFS call fsinfo\n");
nfs_fattr_init(info->fattr);
- status = rpc_call_sync(client, &msg, 0);
+ status = nfs3_rpc(client, NFS3PROC_FSINFO, fhandle, info, NULL);
dprintk("NFS reply fsinfo: %d\n", status);
return status;
}
@@ -721,16 +657,11 @@ static int
nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_pathconf *info)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs3_procedures[NFS3PROC_PATHCONF],
- .rpc_argp = fhandle,
- .rpc_resp = info,
- };
int status;
dprintk("NFS call pathconf\n");
nfs_fattr_init(info->fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs3_rpc(server->client, NFS3PROC_PATHCONF, fhandle, info, NULL);
dprintk("NFS reply pathconf: %d\n", status);
return status;
}
diff -Nurp linux-source-2.6.26.orig/fs/nfs/nfs4proc.c linux-source-2.6.26/fs/nfs/nfs4proc.c
--- linux-source-2.6.26.orig/fs/nfs/nfs4proc.c 2010-08-11 10:07:24.000000000 +0200
+++ linux-source-2.6.26/fs/nfs/nfs4proc.c 2010-08-11 13:23:12.000000000 +0200
@@ -1403,7 +1403,7 @@ nfs4_atomic_open(struct inode *dir, stru
BUG_ON(nd->intent.open.flags & O_CREAT);
}
- cred = rpc_lookup_cred();
+ cred = rpc_lookup_cred(NULL);
if (IS_ERR(cred))
return (struct dentry *)cred;
parent = dentry->d_parent;
@@ -1438,7 +1438,7 @@ nfs4_open_revalidate(struct inode *dir,
struct rpc_cred *cred;
struct nfs4_state *state;
- cred = rpc_lookup_cred();
+ cred = rpc_lookup_cred(NULL);
if (IS_ERR(cred))
return PTR_ERR(cred);
state = nfs4_do_open(dir, &path, openflags, NULL, cred);
@@ -1645,7 +1645,7 @@ static int nfs4_proc_getattr(struct nfs_
*/
static int
nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
- struct iattr *sattr)
+ struct iattr *sattr, struct rpc_groups *fsg)
{
struct rpc_cred *cred;
struct inode *inode = dentry->d_inode;
@@ -1655,7 +1655,7 @@ nfs4_proc_setattr(struct dentry *dentry,
nfs_fattr_init(fattr);
- cred = rpc_lookup_cred();
+ cred = rpc_lookup_cred(NULL);
if (IS_ERR(cred))
return PTR_ERR(cred);
@@ -1733,7 +1733,9 @@ static int _nfs4_proc_lookup(struct inod
return status;
}
-static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+static int nfs4_proc_lookup(struct inode *dir, struct qstr *name,
+ struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+ struct rpc_groups *fsg)
{
struct nfs4_exception exception = { };
int err;
@@ -1881,7 +1883,7 @@ static int nfs4_proc_readlink(struct ino
static int
nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
- int flags, struct nameidata *nd)
+ int flags, struct nameidata *nd, struct rpc_groups *fsg)
{
struct path path = {
.mnt = nd->path.mnt,
@@ -1891,7 +1893,7 @@ nfs4_proc_create(struct inode *dir, stru
struct rpc_cred *cred;
int status = 0;
- cred = rpc_lookup_cred();
+ cred = rpc_lookup_cred(NULL);
if (IS_ERR(cred)) {
status = PTR_ERR(cred);
goto out;
@@ -1948,7 +1950,8 @@ static int _nfs4_proc_remove(struct inod
return status;
}
-static int nfs4_proc_remove(struct inode *dir, struct qstr *name)
+static int nfs4_proc_remove(struct inode *dir, struct qstr *name,
+ struct rpc_groups *fsg)
{
struct nfs4_exception exception = { };
int err;
@@ -2020,7 +2023,8 @@ static int _nfs4_proc_rename(struct inod
}
static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
- struct inode *new_dir, struct qstr *new_name)
+ struct inode *new_dir, struct qstr *new_name,
+ struct rpc_groups *fsg)
{
struct nfs4_exception exception = { };
int err;
@@ -2067,7 +2071,8 @@ static int _nfs4_proc_link(struct inode
return status;
}
-static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+static int nfs4_proc_link(struct inode *inode, struct inode *dir,
+ struct qstr *name, struct rpc_groups *fsg)
{
struct nfs4_exception exception = { };
int err;
@@ -2118,13 +2123,14 @@ static int _nfs4_proc_symlink(struct ino
if (!status) {
update_changeattr(dir, &res.dir_cinfo);
nfs_post_op_update_inode(dir, res.dir_fattr);
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
}
return status;
}
static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry,
- struct page *page, unsigned int len, struct iattr *sattr)
+ struct page *page, unsigned int len, struct iattr *sattr,
+ struct rpc_groups *fsg)
{
struct nfs4_exception exception = { };
int err;
@@ -2171,13 +2177,13 @@ static int _nfs4_proc_mkdir(struct inode
if (!status) {
update_changeattr(dir, &res.dir_cinfo);
nfs_post_op_update_inode(dir, res.dir_fattr);
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ status = nfs_instantiate(dentry, &fhandle, &fattr, NULL);
}
return status;
}
static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
- struct iattr *sattr)
+ struct iattr *sattr, struct rpc_groups *fsg)
{
struct nfs4_exception exception = { };
int err;
@@ -2290,13 +2296,13 @@ static int _nfs4_proc_mknod(struct inode
if (status == 0) {
update_changeattr(dir, &res.dir_cinfo);
nfs_post_op_update_inode(dir, res.dir_fattr);
- status = nfs_instantiate(dentry, &fh, &fattr);
+ status = nfs_instantiate(dentry, &fh, &fattr, NULL);
}
return status;
}
static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
- struct iattr *sattr, dev_t rdev)
+ struct iattr *sattr, dev_t rdev, struct rpc_groups *fsg)
{
struct nfs4_exception exception = { };
int err;
diff -Nurp linux-source-2.6.26.orig/fs/nfs/proc.c linux-source-2.6.26/fs/nfs/proc.c
--- linux-source-2.6.26.orig/fs/nfs/proc.c 2010-08-11 10:07:24.000000000 +0200
+++ linux-source-2.6.26/fs/nfs/proc.c 2010-08-11 13:23:12.000000000 +0200
@@ -6,7 +6,7 @@
* OS-independent nfs remote procedure call functions
*
* Tuned by Alan Cox <A.Cox@swansea.ac.uk> for >3K buffers
- * so at last we can have decent(ish) throughput off a
+ * so at last we can have decent(ish) throughput off a
* Sun server.
*
* Coding optimized and cleaned up by Florian La Roche.
@@ -47,6 +47,34 @@
#define NFSDBG_FACILITY NFSDBG_PROC
+static __inline__ int
+nfs2_rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp,
+ struct rpc_cred *cred, int flags)
+{
+ struct rpc_message msg = {
+ .rpc_proc = &nfs_procedures[proc],
+ .rpc_argp = argp,
+ .rpc_resp = resp,
+ .rpc_cred = cred,
+ };
+ return rpc_call_sync(clnt, &msg, flags);
+}
+
+static int
+nfs2_rpc(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp,
+ struct rpc_groups *fsg)
+{
+ struct rpc_cred *cred;
+ int res;
+
+ cred = rpcauth_lookupcred(clnt->cl_auth, fsg, 0);
+ if (IS_ERR(cred))
+ return PTR_ERR(cred);
+ res = nfs2_rpc_call(clnt, proc, argp, resp, cred, 0);
+ put_rpccred(cred);
+ return res;
+}
+
/*
* Bare-bones access to getattr: this is for nfs_read_super.
*/
@@ -56,29 +84,16 @@ nfs_proc_get_root(struct nfs_server *ser
{
struct nfs_fattr *fattr = info->fattr;
struct nfs2_fsstat fsinfo;
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_GETATTR],
- .rpc_argp = fhandle,
- .rpc_resp = fattr,
- };
int status;
dprintk("%s: call getattr\n", __func__);
nfs_fattr_init(fattr);
- status = rpc_call_sync(server->client, &msg, 0);
- /* Retry with default authentication if different */
- if (status && server->nfs_client->cl_rpcclient != server->client)
- status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
+ status = nfs2_rpc(server->nfs_client->cl_rpcclient, NFSPROC_GETATTR, fhandle, fattr, NULL);
dprintk("%s: reply getattr: %d\n", __func__, status);
if (status)
return status;
dprintk("%s: call statfs\n", __func__);
- msg.rpc_proc = &nfs_procedures[NFSPROC_STATFS];
- msg.rpc_resp = &fsinfo;
- status = rpc_call_sync(server->client, &msg, 0);
- /* Retry with default authentication if different */
- if (status && server->nfs_client->cl_rpcclient != server->client)
- status = rpc_call_sync(server->nfs_client->cl_rpcclient, &msg, 0);
+ status = nfs2_rpc(server->nfs_client->cl_rpcclient, NFSPROC_STATFS, fhandle, &fsinfo, NULL);
dprintk("%s: reply statfs: %d\n", __func__, status);
if (status)
return status;
@@ -101,34 +116,24 @@ static int
nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
struct nfs_fattr *fattr)
{
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_GETATTR],
- .rpc_argp = fhandle,
- .rpc_resp = fattr,
- };
int status;
dprintk("NFS call getattr\n");
nfs_fattr_init(fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs2_rpc(server->client, NFSPROC_GETATTR, fhandle, fattr, NULL);
dprintk("NFS reply getattr: %d\n", status);
return status;
}
static int
nfs_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
- struct iattr *sattr)
+ struct iattr *sattr, struct rpc_groups *fsg)
{
struct inode *inode = dentry->d_inode;
- struct nfs_sattrargs arg = {
+ struct nfs_sattrargs arg = {
.fh = NFS_FH(inode),
.sattr = sattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_SETATTR],
- .rpc_argp = &arg,
- .rpc_resp = fattr,
- };
int status;
/* Mask out the non-modebit related stuff from attr->ia_mode */
@@ -136,7 +141,7 @@ nfs_proc_setattr(struct dentry *dentry,
dprintk("NFS call setattr\n");
nfs_fattr_init(fattr);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(inode), NFSPROC_SETATTR, &arg, fattr, fsg);
if (status == 0)
nfs_setattr_update_inode(inode, sattr);
dprintk("NFS reply setattr: %d\n", status);
@@ -145,7 +150,8 @@ nfs_proc_setattr(struct dentry *dentry,
static int
nfs_proc_lookup(struct inode *dir, struct qstr *name,
- struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+ struct nfs_fh *fhandle, struct nfs_fattr *fattr,
+ struct rpc_groups *fsg)
{
struct nfs_diropargs arg = {
.fh = NFS_FH(dir),
@@ -156,16 +162,11 @@ nfs_proc_lookup(struct inode *dir, struc
.fh = fhandle,
.fattr = fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_LOOKUP],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
dprintk("NFS call lookup %s\n", name->name);
nfs_fattr_init(fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_LOOKUP, &arg, &res, fsg);
dprintk("NFS reply lookup: %d\n", status);
return status;
}
@@ -179,21 +180,17 @@ static int nfs_proc_readlink(struct inod
.pglen = pglen,
.pages = &page
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_READLINK],
- .rpc_argp = &args,
- };
int status;
dprintk("NFS call readlink\n");
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(inode), NFSPROC_READLINK, &args, NULL, NULL);
dprintk("NFS reply readlink: %d\n", status);
return status;
}
static int
nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
- int flags, struct nameidata *nd)
+ int flags, struct nameidata *nd, struct rpc_groups *fsg)
{
struct nfs_fh fhandle;
struct nfs_fattr fattr;
@@ -207,19 +204,14 @@ nfs_proc_create(struct inode *dir, struc
.fh = &fhandle,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_CREATE],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
nfs_fattr_init(&fattr);
dprintk("NFS call create %s\n", dentry->d_name.name);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, fsg);
nfs_mark_for_revalidate(dir);
if (status == 0)
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ status = nfs_instantiate(dentry, &fhandle, &fattr, fsg);
dprintk("NFS reply create: %d\n", status);
return status;
}
@@ -229,7 +221,7 @@ nfs_proc_create(struct inode *dir, struc
*/
static int
nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
- dev_t rdev)
+ dev_t rdev, struct rpc_groups *fsg)
{
struct nfs_fh fhandle;
struct nfs_fattr fattr;
@@ -243,11 +235,6 @@ nfs_proc_mknod(struct inode *dir, struct
.fh = &fhandle,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_CREATE],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status, mode;
dprintk("NFS call mknod %s\n", dentry->d_name.name);
@@ -262,36 +249,32 @@ nfs_proc_mknod(struct inode *dir, struct
}
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, fsg);
nfs_mark_for_revalidate(dir);
if (status == -EINVAL && S_ISFIFO(mode)) {
sattr->ia_mode = mode;
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, fsg);
}
if (status == 0)
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ status = nfs_instantiate(dentry, &fhandle, &fattr, fsg);
dprintk("NFS reply mknod: %d\n", status);
return status;
}
static int
-nfs_proc_remove(struct inode *dir, struct qstr *name)
+nfs_proc_remove(struct inode *dir, struct qstr *name, struct rpc_groups *fsg)
{
struct nfs_removeargs arg = {
.fh = NFS_FH(dir),
.name.len = name->len,
.name.name = name->name,
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_REMOVE],
- .rpc_argp = &arg,
- };
int status;
dprintk("NFS call remove %s\n", name->name);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_REMOVE, &arg, NULL, fsg);
nfs_mark_for_revalidate(dir);
dprintk("NFS reply remove: %d\n", status);
@@ -312,7 +295,8 @@ static int nfs_proc_unlink_done(struct r
static int
nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
- struct inode *new_dir, struct qstr *new_name)
+ struct inode *new_dir, struct qstr *new_name,
+ struct rpc_groups *fsg)
{
struct nfs_renameargs arg = {
.fromfh = NFS_FH(old_dir),
@@ -322,14 +306,10 @@ nfs_proc_rename(struct inode *old_dir, s
.toname = new_name->name,
.tolen = new_name->len
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_RENAME],
- .rpc_argp = &arg,
- };
int status;
dprintk("NFS call rename %s -> %s\n", old_name->name, new_name->name);
- status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(old_dir), NFSPROC_RENAME, &arg, NULL, fsg);
nfs_mark_for_revalidate(old_dir);
nfs_mark_for_revalidate(new_dir);
dprintk("NFS reply rename: %d\n", status);
@@ -337,7 +317,8 @@ nfs_proc_rename(struct inode *old_dir, s
}
static int
-nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
+nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name,
+ struct rpc_groups *fsg)
{
struct nfs_linkargs arg = {
.fromfh = NFS_FH(inode),
@@ -345,14 +326,10 @@ nfs_proc_link(struct inode *inode, struc
.toname = name->name,
.tolen = name->len
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_LINK],
- .rpc_argp = &arg,
- };
int status;
dprintk("NFS call link %s\n", name->name);
- status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, fsg);
nfs_mark_for_revalidate(inode);
nfs_mark_for_revalidate(dir);
dprintk("NFS reply link: %d\n", status);
@@ -361,7 +338,7 @@ nfs_proc_link(struct inode *inode, struc
static int
nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
- unsigned int len, struct iattr *sattr)
+ unsigned int len, struct iattr *sattr, struct rpc_groups *fsg)
{
struct nfs_fh fhandle;
struct nfs_fattr fattr;
@@ -373,10 +350,6 @@ nfs_proc_symlink(struct inode *dir, stru
.pathlen = len,
.sattr = sattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_SYMLINK],
- .rpc_argp = &arg,
- };
int status;
if (len > NFS2_MAXPATHLEN)
@@ -384,7 +357,7 @@ nfs_proc_symlink(struct inode *dir, stru
dprintk("NFS call symlink %s\n", dentry->d_name.name);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_SYMLINK, &arg, NULL, fsg);
nfs_mark_for_revalidate(dir);
/*
@@ -395,7 +368,7 @@ nfs_proc_symlink(struct inode *dir, stru
if (status == 0) {
nfs_fattr_init(&fattr);
fhandle.size = 0;
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ status = nfs_instantiate(dentry, &fhandle, &fattr, fsg);
}
dprintk("NFS reply symlink: %d\n", status);
@@ -403,7 +376,8 @@ nfs_proc_symlink(struct inode *dir, stru
}
static int
-nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
+nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+ struct rpc_groups *fsg)
{
struct nfs_fh fhandle;
struct nfs_fattr fattr;
@@ -417,39 +391,30 @@ nfs_proc_mkdir(struct inode *dir, struct
.fh = &fhandle,
.fattr = &fattr
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_MKDIR],
- .rpc_argp = &arg,
- .rpc_resp = &res,
- };
int status;
dprintk("NFS call mkdir %s\n", dentry->d_name.name);
nfs_fattr_init(&fattr);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, fsg);
nfs_mark_for_revalidate(dir);
if (status == 0)
- status = nfs_instantiate(dentry, &fhandle, &fattr);
+ status = nfs_instantiate(dentry, &fhandle, &fattr, fsg);
dprintk("NFS reply mkdir: %d\n", status);
return status;
}
static int
-nfs_proc_rmdir(struct inode *dir, struct qstr *name)
+nfs_proc_rmdir(struct inode *dir, struct qstr *name, struct rpc_groups *fsg)
{
struct nfs_diropargs arg = {
.fh = NFS_FH(dir),
.name = name->name,
.len = name->len
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_RMDIR],
- .rpc_argp = &arg,
- };
int status;
dprintk("NFS call rmdir %s\n", name->name);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs2_rpc(NFS_CLIENT(dir), NFSPROC_RMDIR, &arg, NULL, fsg);
nfs_mark_for_revalidate(dir);
dprintk("NFS reply rmdir: %d\n", status);
return status;
@@ -473,15 +438,10 @@ nfs_proc_readdir(struct dentry *dentry,
.count = count,
.pages = &page,
};
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_READDIR],
- .rpc_argp = &arg,
- .rpc_cred = cred,
- };
int status;
dprintk("NFS call readdir %d\n", (unsigned int)cookie);
- status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
+ status = nfs2_rpc_call(NFS_CLIENT(dir), NFSPROC_READDIR, &arg, NULL, cred, 0);
nfs_invalidate_atime(dir);
@@ -494,16 +454,11 @@ nfs_proc_statfs(struct nfs_server *serve
struct nfs_fsstat *stat)
{
struct nfs2_fsstat fsinfo;
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_STATFS],
- .rpc_argp = fhandle,
- .rpc_resp = &fsinfo,
- };
int status;
dprintk("NFS call statfs\n");
nfs_fattr_init(stat->fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs2_rpc(server->client, NFSPROC_STATFS, fhandle, &fsinfo, NULL);
dprintk("NFS reply statfs: %d\n", status);
if (status)
goto out;
@@ -522,16 +477,11 @@ nfs_proc_fsinfo(struct nfs_server *serve
struct nfs_fsinfo *info)
{
struct nfs2_fsstat fsinfo;
- struct rpc_message msg = {
- .rpc_proc = &nfs_procedures[NFSPROC_STATFS],
- .rpc_argp = fhandle,
- .rpc_resp = &fsinfo,
- };
int status;
dprintk("NFS call fsinfo\n");
nfs_fattr_init(info->fattr);
- status = rpc_call_sync(server->client, &msg, 0);
+ status = nfs2_rpc(server->client, NFSPROC_STATFS, fhandle, &fsinfo, NULL);
dprintk("NFS reply fsinfo: %d\n", status);
if (status)
goto out;
diff -Nurp linux-source-2.6.26.orig/fs/nfs/unlink.c linux-source-2.6.26/fs/nfs/unlink.c
--- linux-source-2.6.26.orig/fs/nfs/unlink.c 2010-08-11 10:07:24.000000000 +0200
+++ linux-source-2.6.26/fs/nfs/unlink.c 2010-08-11 13:23:12.000000000 +0200
@@ -234,7 +234,12 @@ nfs_async_unlink(struct inode *dir, stru
if (data == NULL)
goto out;
- data->cred = rpc_lookup_cred();
+ if (NFS_PROTO(dir)->version > 3)
+ data->cred = rpc_lookup_cred(NULL);
+ else {
+ struct rpc_groups fsg = { 1, { dir->i_gid } };
+ data->cred = rpc_lookup_cred(&fsg);
+ }
if (IS_ERR(data->cred)) {
status = PTR_ERR(data->cred);
goto out_free;
diff -Nurp linux-source-2.6.26.orig/include/linux/nfs_fs.h linux-source-2.6.26/include/linux/nfs_fs.h
--- linux-source-2.6.26.orig/include/linux/nfs_fs.h 2010-08-11 10:07:36.000000000 +0200
+++ linux-source-2.6.26/include/linux/nfs_fs.h 2010-08-11 13:23:12.000000000 +0200
@@ -407,7 +407,8 @@ extern const struct file_operations nfs_
extern struct dentry_operations nfs_dentry_operations;
extern void nfs_force_lookup_revalidate(struct inode *dir);
-extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
+extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh,
+ struct nfs_fattr *fattr, struct rpc_groups *fsg);
extern int nfs_may_open(struct inode *inode, struct rpc_cred *cred, int openflags);
extern void nfs_access_zap_cache(struct inode *inode);
diff -Nurp linux-source-2.6.26.orig/include/linux/nfs_xdr.h linux-source-2.6.26/include/linux/nfs_xdr.h
--- linux-source-2.6.26.orig/include/linux/nfs_xdr.h 2010-08-11 10:07:36.000000000 +0200
+++ linux-source-2.6.26/include/linux/nfs_xdr.h 2010-08-11 13:23:12.000000000 +0200
@@ -777,7 +777,7 @@ struct nfs_write_data {
struct nfs_access_entry;
/*
- * RPC procedure vector for NFSv2/NFSv3 demuxing
+ * RPC procedure vector for NFSv2/NFSv3/NFSv4 demuxing
*/
struct nfs_rpc_ops {
u32 version; /* Protocol version */
@@ -793,28 +793,32 @@ struct nfs_rpc_ops {
int (*getattr) (struct nfs_server *, struct nfs_fh *,
struct nfs_fattr *);
int (*setattr) (struct dentry *, struct nfs_fattr *,
- struct iattr *);
+ struct iattr *, struct rpc_groups *);
int (*lookup) (struct inode *, struct qstr *,
- struct nfs_fh *, struct nfs_fattr *);
+ struct nfs_fh *, struct nfs_fattr *,
+ struct rpc_groups *);
int (*access) (struct inode *, struct nfs_access_entry *);
int (*readlink)(struct inode *, struct page *, unsigned int,
unsigned int);
int (*create) (struct inode *, struct dentry *,
- struct iattr *, int, struct nameidata *);
- int (*remove) (struct inode *, struct qstr *);
+ struct iattr *, int, struct nameidata *,
+ struct rpc_groups *);
+ int (*remove) (struct inode *, struct qstr *, struct rpc_groups *);
void (*unlink_setup) (struct rpc_message *, struct inode *dir);
int (*unlink_done) (struct rpc_task *, struct inode *);
int (*rename) (struct inode *, struct qstr *,
- struct inode *, struct qstr *);
- int (*link) (struct inode *, struct inode *, struct qstr *);
+ struct inode *, struct qstr *, struct rpc_groups *);
+ int (*link) (struct inode *, struct inode *, struct qstr *,
+ struct rpc_groups *);
int (*symlink) (struct inode *, struct dentry *, struct page *,
- unsigned int, struct iattr *);
- int (*mkdir) (struct inode *, struct dentry *, struct iattr *);
- int (*rmdir) (struct inode *, struct qstr *);
+ unsigned int, struct iattr *, struct rpc_groups *);
+ int (*mkdir) (struct inode *, struct dentry *, struct iattr *,
+ struct rpc_groups *);
+ int (*rmdir) (struct inode *, struct qstr *, struct rpc_groups *);
int (*readdir) (struct dentry *, struct rpc_cred *,
u64, struct page *, unsigned int, int);
int (*mknod) (struct inode *, struct dentry *, struct iattr *,
- dev_t);
+ dev_t, struct rpc_groups *);
int (*statfs) (struct nfs_server *, struct nfs_fh *,
struct nfs_fsstat *);
int (*fsinfo) (struct nfs_server *, struct nfs_fh *,
diff -Nurp linux-source-2.6.26.orig/include/linux/sunrpc/auth.h linux-source-2.6.26/include/linux/sunrpc/auth.h
--- linux-source-2.6.26.orig/include/linux/sunrpc/auth.h 2010-08-11 10:07:37.000000000 +0200
+++ linux-source-2.6.26/include/linux/sunrpc/auth.h 2010-08-11 13:23:12.000000000 +0200
@@ -15,17 +15,23 @@
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/xdr.h>
+#include <linux/sched.h>
#include <asm/atomic.h>
#include <linux/rcupdate.h>
/* size of the nodename buffer */
#define UNX_MAXNODENAME 32
+struct rpc_groups {
+ int ngroups;
+ gid_t groups[RPC_MAXGROUPS];
+};
+
/* Work around the lack of a VFS credential */
struct auth_cred {
uid_t uid;
gid_t gid;
- struct group_info *group_info;
+ struct rpc_groups rg;
unsigned char machine_cred : 1;
};
@@ -130,7 +136,7 @@ void __init rpcauth_init_module(void);
void __exit rpcauth_remove_module(void);
void __exit rpc_destroy_generic_auth(void);
-struct rpc_cred * rpc_lookup_cred(void);
+struct rpc_cred * rpc_lookup_cred(struct rpc_groups *);
struct rpc_cred * rpc_lookup_machine_cred(void);
int rpcauth_register(const struct rpc_authops *);
int rpcauth_unregister(const struct rpc_authops *);
@@ -138,7 +144,7 @@ struct rpc_auth * rpcauth_create(rpc_aut
void rpcauth_release(struct rpc_auth *);
struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
-struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int);
+struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, struct rpc_groups *, int);
void rpcauth_bindcred(struct rpc_task *, struct rpc_cred *, int);
void rpcauth_generic_bind_cred(struct rpc_task *, struct rpc_cred *);
void put_rpccred(struct rpc_cred *);
diff -Nurp linux-source-2.6.26.orig/include/linux/sunrpc/msg_prot.h linux-source-2.6.26/include/linux/sunrpc/msg_prot.h
--- linux-source-2.6.26.orig/include/linux/sunrpc/msg_prot.h 2010-08-11 10:07:37.000000000 +0200
+++ linux-source-2.6.26/include/linux/sunrpc/msg_prot.h 2010-08-11 13:23:12.000000000 +0200
@@ -79,6 +79,7 @@ enum rpc_auth_stat {
};
#define RPC_MAXNETNAMELEN 256
+#define RPC_MAXGROUPS 16
/*
* From RFC 1831:
diff -Nurp linux-source-2.6.26.orig/include/linux/sunrpc/svcauth.h linux-source-2.6.26/include/linux/sunrpc/svcauth.h
--- linux-source-2.6.26.orig/include/linux/sunrpc/svcauth.h 2010-08-11 10:07:37.000000000 +0200
+++ linux-source-2.6.26/include/linux/sunrpc/svcauth.h 2010-08-11 13:23:12.000000000 +0200
@@ -16,7 +16,6 @@
#include <linux/sunrpc/cache.h>
#include <linux/hash.h>
-#define SVC_CRED_NGROUPS 32
struct svc_cred {
uid_t cr_uid;
gid_t cr_gid;
diff -Nurp linux-source-2.6.26.orig/net/sunrpc/auth.c linux-source-2.6.26/net/sunrpc/auth.c
--- linux-source-2.6.26.orig/net/sunrpc/auth.c 2010-08-11 10:07:43.000000000 +0200
+++ linux-source-2.6.26/net/sunrpc/auth.c 2010-08-11 13:23:12.000000000 +0200
@@ -17,8 +17,11 @@
#ifdef RPC_DEBUG
# define RPCDBG_FACILITY RPCDBG_AUTH
+# define RG(rg,i) ((i) < (rg).ngroups ? (int)(rg).groups[i] : -1)
#endif
+static void rpcauth_add_groups(struct auth_cred *acred, struct rpc_groups *rg);
+
static DEFINE_SPINLOCK(rpc_authflavor_lock);
static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
&authnull_ops, /* AUTH_NULL */
@@ -348,22 +351,22 @@ out:
EXPORT_SYMBOL_GPL(rpcauth_lookup_credcache);
struct rpc_cred *
-rpcauth_lookupcred(struct rpc_auth *auth, int flags)
+rpcauth_lookupcred(struct rpc_auth *auth, struct rpc_groups *rg, int flags)
{
struct auth_cred acred = {
.uid = current->fsuid,
- .gid = current->fsgid,
- .group_info = current->group_info,
};
struct rpc_cred *ret;
- dprintk("RPC: looking up %s cred\n",
- auth->au_ops->au_name);
- get_group_info(acred.group_info);
+ dprintk("RPC: looking up %s cred\n", auth->au_ops->au_name);
+
+ rpcauth_add_groups(&acred, rg);
ret = auth->au_ops->lookup_cred(auth, &acred, flags);
- put_group_info(acred.group_info);
+
+ dprintk("RPC: cred %p\n", ret);
return ret;
}
+EXPORT_SYMBOL_GPL(rpcauth_lookupcred);
void
rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
@@ -382,6 +385,41 @@ rpcauth_init_cred(struct rpc_cred *cred,
}
EXPORT_SYMBOL_GPL(rpcauth_init_cred);
+/*
+ * Generic function for adding groups to acred. When there are too many then
+ * try to be smart by picking only the relevant ones from our secondary group list.
+ */
+static void rpcauth_add_groups(struct auth_cred *acred, struct rpc_groups *rg)
+{
+ int i, n, ngroups;
+ gid_t gid;
+
+ acred->gid = current->fsgid;
+ ngroups = current->group_info ? current->group_info->ngroups : 0;
+ n = ngroups;
+ if (n <= RPC_MAXGROUPS)
+ rg = NULL;
+ else
+ n = RPC_MAXGROUPS; /* too many groups for AUTH_UNIX */
+ if (rg) {
+ n = 0; /* pick the few relevant groups we're a member of */
+ for (i = 0; i < rg->ngroups; ++i) {
+ gid = rg->groups[i];
+ if (in_group_p(gid))
+ acred->rg.groups[n++] = gid;
+ }
+ acred->rg.ngroups = n;
+ dprintk("RPC: %s(): rg=%d:%d,%d,%d -> %d:%d,%d,%d\n", __func__,
+ rg->ngroups, RG(*rg, 0), RG(*rg, 1), RG(*rg, 2),
+ n, RG(acred->rg, 0), RG(acred->rg, 1), RG(acred->rg, 2));
+ } else {
+ dprintk("RPC: %s(): ngroups=%d\n", __func__, ngroups);
+ for (i = 0; i < n; ++i)
+ acred->rg.groups[i] = GROUP_AT(current->group_info, i);
+ acred->rg.ngroups = n;
+ }
+}
+
void
rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred)
{
@@ -418,7 +456,7 @@ rpcauth_bind_new_cred(struct rpc_task *t
dprintk("RPC: %5u looking up %s cred\n",
task->tk_pid, auth->au_ops->au_name);
- ret = rpcauth_lookupcred(auth, 0);
+ ret = rpcauth_lookupcred(auth, NULL, 0);
if (!IS_ERR(ret))
task->tk_msg.rpc_cred = ret;
else
diff -Nurp linux-source-2.6.26.orig/net/sunrpc/auth_generic.c linux-source-2.6.26/net/sunrpc/auth_generic.c
--- linux-source-2.6.26.orig/net/sunrpc/auth_generic.c 2010-08-11 10:07:43.000000000 +0200
+++ linux-source-2.6.26/net/sunrpc/auth_generic.c 2010-08-11 13:23:21.000000000 +0200
@@ -32,9 +32,9 @@ static const struct rpc_credops generic_
/*
* Public call interface
*/
-struct rpc_cred *rpc_lookup_cred(void)
+struct rpc_cred *rpc_lookup_cred(struct rpc_groups *rg)
{
- return rpcauth_lookupcred(&generic_auth, 0);
+ return rpcauth_lookupcred(&generic_auth, rg, 0);
}
EXPORT_SYMBOL_GPL(rpc_lookup_cred);
@@ -89,12 +89,7 @@ generic_create_cred(struct rpc_auth *aut
rpcauth_init_cred(&gcred->gc_base, acred, &generic_auth, &generic_credops);
gcred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
- gcred->acred.uid = acred->uid;
- gcred->acred.gid = acred->gid;
- gcred->acred.group_info = acred->group_info;
- if (gcred->acred.group_info != NULL)
- get_group_info(gcred->acred.group_info);
- gcred->acred.machine_cred = acred->machine_cred;
+ gcred->acred = *acred;
dprintk("RPC: allocated %s cred %p for uid %d gid %d\n",
gcred->acred.machine_cred ? "machine" : "generic",
@@ -108,8 +103,6 @@ generic_free_cred(struct rpc_cred *cred)
struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
dprintk("RPC: generic_free_cred %p\n", gcred);
- if (gcred->acred.group_info != NULL)
- put_group_info(gcred->acred.group_info);
kfree(gcred);
}
@@ -133,29 +126,14 @@ static int
generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
{
struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
- int i;
if (gcred->acred.uid != acred->uid ||
gcred->acred.gid != acred->gid ||
+ gcred->acred.rg.ngroups != acred->rg.ngroups ||
+ memcmp(gcred->acred.rg.groups, acred->rg.groups, acred->rg.ngroups * sizeof (gid_t)) ||
gcred->acred.machine_cred != acred->machine_cred)
- goto out_nomatch;
-
- /* Optimisation in the case where pointers are identical... */
- if (gcred->acred.group_info == acred->group_info)
- goto out_match;
-
- /* Slow path... */
- if (gcred->acred.group_info->ngroups != acred->group_info->ngroups)
- goto out_nomatch;
- for (i = 0; i < gcred->acred.group_info->ngroups; i++) {
- if (GROUP_AT(gcred->acred.group_info, i) !=
- GROUP_AT(acred->group_info, i))
- goto out_nomatch;
- }
-out_match:
+ return 0;
return 1;
-out_nomatch:
- return 0;
}
void __init rpc_init_generic_auth(void)
diff -Nurp linux-source-2.6.26.orig/net/sunrpc/auth_gss/auth_gss.c linux-source-2.6.26/net/sunrpc/auth_gss/auth_gss.c
--- linux-source-2.6.26.orig/net/sunrpc/auth_gss/auth_gss.c 2010-08-11 10:07:43.000000000 +0200
+++ linux-source-2.6.26/net/sunrpc/auth_gss/auth_gss.c 2010-08-11 13:23:12.000000000 +0200
@@ -63,8 +63,6 @@ static const struct rpc_credops gss_null
# define RPCDBG_FACILITY RPCDBG_AUTH
#endif
-#define NFS_NGROUPS 16
-
#define GSS_CRED_SLACK 1024 /* XXX: unused */
/* length of a krb5 verifier (48), plus data added before arguments when
* using integrity (two 4-byte integers): */
diff -Nurp linux-source-2.6.26.orig/net/sunrpc/auth_unix.c linux-source-2.6.26/net/sunrpc/auth_unix.c
--- linux-source-2.6.26.orig/net/sunrpc/auth_unix.c 2010-08-11 10:07:43.000000000 +0200
+++ linux-source-2.6.26/net/sunrpc/auth_unix.c 2010-08-11 13:23:12.000000000 +0200
@@ -12,12 +12,10 @@
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/auth.h>
-#define NFS_NGROUPS 16
-
struct unx_cred {
struct rpc_cred uc_base;
gid_t uc_gid;
- gid_t uc_gids[NFS_NGROUPS];
+ gid_t uc_gids[RPC_MAXGROUPS];
};
#define uc_uid uc_base.cr_uid
@@ -60,8 +58,7 @@ static struct rpc_cred *
unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
{
struct unx_cred *cred;
- unsigned int groups = 0;
- unsigned int i;
+ int n;
dprintk("RPC: allocating UNIX cred for uid %d gid %d\n",
acred->uid, acred->gid);
@@ -72,16 +69,11 @@ unx_create_cred(struct rpc_auth *auth, s
rpcauth_init_cred(&cred->uc_base, acred, auth, &unix_credops);
cred->uc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;
- if (acred->group_info != NULL)
- groups = acred->group_info->ngroups;
- if (groups > NFS_NGROUPS)
- groups = NFS_NGROUPS;
-
+ n = acred->rg.ngroups;
cred->uc_gid = acred->gid;
- for (i = 0; i < groups; i++)
- cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
- if (i < NFS_NGROUPS)
- cred->uc_gids[i] = NOGROUP;
+ memcpy(cred->uc_gids, acred->rg.groups, n * sizeof (gid_t));
+ if (n < RPC_MAXGROUPS)
+ cred->uc_gids[n] = NOGROUP;
return &cred->uc_base;
}
@@ -115,21 +107,12 @@ static int
unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags)
{
struct unx_cred *cred = container_of(rcred, struct unx_cred, uc_base);
- unsigned int groups = 0;
- unsigned int i;
-
+ int n = acred->rg.ngroups;
if (cred->uc_uid != acred->uid || cred->uc_gid != acred->gid)
return 0;
- if (acred->group_info != NULL)
- groups = acred->group_info->ngroups;
- if (groups > NFS_NGROUPS)
- groups = NFS_NGROUPS;
- for (i = 0; i < groups ; i++)
- if (cred->uc_gids[i] != GROUP_AT(acred->group_info, i))
- return 0;
- return 1;
+ return !memcmp(cred->uc_gids, acred->rg.groups, n * sizeof (gid_t));
}
/*
@@ -156,7 +139,7 @@ unx_marshal(struct rpc_task *task, __be3
*p++ = htonl((u32) cred->uc_uid);
*p++ = htonl((u32) cred->uc_gid);
hold = p++;
- for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
+ for (i = 0; i < RPC_MAXGROUPS && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
*p++ = htonl((u32) cred->uc_gids[i]);
*hold = htonl(p - hold - 1); /* gid array length */
*base = htonl((p - base - 1) << 2); /* cred length */
diff -Nurp linux-source-2.6.26.orig/net/sunrpc/svcauth_unix.c linux-source-2.6.26/net/sunrpc/svcauth_unix.c
--- linux-source-2.6.26.orig/net/sunrpc/svcauth_unix.c 2010-08-11 10:07:43.000000000 +0200
+++ linux-source-2.6.26/net/sunrpc/svcauth_unix.c 2010-08-11 13:23:12.000000000 +0200
@@ -815,7 +815,7 @@ svcauth_unix_accept(struct svc_rqst *rqs
cred->cr_uid = svc_getnl(argv); /* uid */
cred->cr_gid = svc_getnl(argv); /* gid */
slen = svc_getnl(argv); /* gids length */
- if (slen > 16 || (len -= (slen + 2)*4) < 0)
+ if (slen > RPC_MAXGROUPS || (len -= (slen + 2)*4) < 0)
goto badcred;
if (unix_gid_find(cred->cr_uid, &cred->cr_group_info, rqstp)
== -EAGAIN)
Reply to: