diff options
Diffstat (limited to 'netfs.c')
-rw-r--r-- | netfs.c | 652 |
1 files changed, 315 insertions, 337 deletions
@@ -1,467 +1,445 @@ -/* procfs -- a translator for providing GNU/Linux compatible - proc pseudo-filesystem +/* Hurd /proc filesystem, interface with libnetfs. + Copyright (C) 2010 Free Software Foundation, Inc. - Copyright (C) 2008, FSF. - Written as a Summer of Code Project - - procfs is free software; you can redistribute it and/or + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - procfs is distributed in the hope that it will be useful, but + The GNU Hurd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. -*/ + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <stddef.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> +#include <hurd/netfs.h> +#include <hurd/fshelp.h> +#include <sys/mman.h> +#include <mach/vm_param.h> #include <dirent.h> -#include <string.h> +#include <fcntl.h> +#include "procfs.h" -#include <sys/mman.h> -#include <sys/stat.h> -#include <hurd/netfs.h> +#define PROCFS_SERVER_NAME "procfs" +#define PROCFS_SERVER_VERSION "0.1.0" +#define PROCFS_MAXSYMLINKS 16 -#include "procfs.h" + +/* Interesting libnetfs callback functions. */ -/* Trivial definitions. */ +/* The user must define this variable. Set this to the name of the + filesystem server. */ +char *netfs_server_name = PROCFS_SERVER_NAME; -/* Make sure that NP->nn_stat is filled with current information. CRED - identifies the user responsible for the operation. */ -error_t -netfs_validate_stat (struct node *node, struct iouser *cred) -{ - return procfs_refresh_node (node); -} +/* The user must define this variables. Set this to be the server + version number. */ +char *netfs_server_version = PROCFS_SERVER_VERSION; -/* This should sync the file NODE completely to disk, for the user CRED. If - WAIT is set, return only after sync is completely finished. */ -error_t -netfs_attempt_sync (struct iouser *cred, struct node *node, int wait) +/* Maximum number of symlinks to follow before returning ELOOP. */ +int netfs_maxsymlinks = PROCFS_MAXSYMLINKS; + +/* The user must define this function. Make sure that NP->nn_stat is + filled with the most current information. CRED identifies the user + responsible for the operation. NP is locked. */ +error_t netfs_validate_stat (struct node *np, struct iouser *cred) { + char *contents; + ssize_t contents_len; + error_t err; + + /* Only symlinks need to have their size filled, before a read is + attempted. */ + if (! S_ISLNK (np->nn_stat.st_mode)) + return 0; + + err = procfs_get_contents (np, &contents, &contents_len); + if (err) + return err; + + np->nn_stat.st_size = contents_len; return 0; } -/* Attempt to create a new directory named NAME in DIR for USER with mode - MODE. */ -error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, - char *name, mode_t mode) +/* The user must define this function. Read from the locked file NP + for user CRED starting at OFFSET and continuing for up to *LEN + bytes. Put the data at DATA. Set *LEN to the amount successfully + read upon return. */ +error_t netfs_attempt_read (struct iouser *cred, struct node *np, + loff_t offset, size_t *len, void *data) { - return EROFS; -} + char *contents; + ssize_t contents_len; + error_t err; -/* Attempt to remove directory named NAME in DIR for USER. */ -error_t netfs_attempt_rmdir (struct iouser *user, - struct node *dir, char *name) -{ - return EROFS; -} + if (offset == 0) + procfs_refresh (np); -/* Attempt to set the passive translator record for FILE to ARGZ (of length - ARGZLEN) for user CRED. */ -error_t netfs_set_translator (struct iouser *cred, struct node *node, - char *argz, size_t argzlen) -{ - return EROFS; -} + err = procfs_get_contents (np, &contents, &contents_len); + if (err) + return err; -/* Attempt to create a file named NAME in DIR for USER with MODE. Set *NODE - to the new node upon return. On any error, clear *NODE. *NODE should be - locked on success; no matter what, unlock DIR before returning. */ -error_t -netfs_attempt_create_file (struct iouser *user, struct node *dir, - char *name, mode_t mode, struct node **node) -{ - *node = NULL; - mutex_unlock (&dir->lock); - return EROFS; + contents += offset; + contents_len -= offset; + + if (*len > contents_len) + *len = contents_len; + if (*len < 0) + *len = 0; + + memcpy (data, contents, *len); + return 0; } -/* Node NODE is being opened by USER, with FLAGS. NEWNODE is nonzero if we - just created this node. Return an error if we should not permit the open - to complete because of a permission restriction. */ -error_t -netfs_check_open_permissions (struct iouser *user, struct node *node, - int flags, int newnode) +/* The user must define this function. Read the contents of locked + node NP (a symlink), for USER, into BUF. */ +error_t netfs_attempt_readlink (struct iouser *user, struct node *np, + char *buf) { - error_t err = procfs_refresh_node (node); - if (!err && (flags & O_READ)) - err = fshelp_access (&node->nn_stat, S_IREAD, user); - if (!err && (flags & O_WRITE)) - err = fshelp_access (&node->nn_stat, S_IWRITE, user); - if (!err && (flags & O_EXEC)) - err = fshelp_access (&node->nn_stat, S_IEXEC, user); - return err; + char *contents; + ssize_t contents_len; + error_t err; + + err = procfs_get_contents (np, &contents, &contents_len); + if (err) + return err; + + assert (contents_len == np->nn_stat.st_size); + memcpy (buf, contents, contents_len); + return 0; } -/* This should attempt a utimes call for the user specified by CRED on node - NODE, to change the atime to ATIME and the mtime to MTIME. */ -error_t -netfs_attempt_utimes (struct iouser *cred, struct node *node, - struct timespec *atime, struct timespec *mtime) +/* Helper function for netfs_get_dirents() below. CONTENTS is an argz + vector of directory entry names, as returned by procfs_get_contents(). + Convert at most NENTRIES of them to dirent structures, put them in + DATA (if not NULL), write the number of entries processed in *AMT and + return the required/used space in DATACNT. */ +static int putentries (char *contents, size_t contents_len, int nentries, + char *data, mach_msg_type_number_t *datacnt) { - error_t err = procfs_refresh_node (node); - int flags = TOUCH_CTIME; - - if (! err) - err = fshelp_isowner (&node->nn_stat, cred); + int i; - if (! err) + *datacnt = 0; + for (i = 0; contents_len && (nentries < 0 || i < nentries); i++) { - if (atime) - node->nn_stat.st_atim = *atime; - else - flags |= TOUCH_ATIME; + int namlen = strlen (contents); + int reclen = sizeof (struct dirent) + namlen; - if (mtime) - node->nn_stat.st_mtim = *mtime; - else - flags |= TOUCH_MTIME; - - fshelp_touch (&node->nn_stat, flags, procfs_maptime); + if (data) + { + struct dirent *d = (struct dirent *) (data + *datacnt); + d->d_fileno = 42; /* XXX */ + d->d_namlen = namlen; + d->d_reclen = reclen; + d->d_type = DT_UNKNOWN; + strcpy (d->d_name, contents); + } + + *datacnt += reclen; + contents += namlen + 1; + contents_len -= namlen + 1; } - return err; + return i; } -/* Return the valid access types (bitwise OR of O_READ, O_WRITE, and O_EXEC) - in *TYPES for file NODE and user CRED. */ -error_t -netfs_report_access (struct iouser *cred, struct node *node, int *types) +/* The user must define this function. Fill the array *DATA of size + BUFSIZE with up to NENTRIES dirents from DIR (which is locked) + starting with entry ENTRY for user CRED. The number of entries in + the array is stored in *AMT and the number of bytes in *DATACNT. + If the supplied buffer is not large enough to hold the data, it + should be grown. */ +error_t netfs_get_dirents (struct iouser *cred, struct node *dir, + int entry, int nentries, char **data, + mach_msg_type_number_t *datacnt, + vm_size_t bufsize, int *amt) { - error_t err = procfs_refresh_node (node); + char *contents; + ssize_t contents_len; + error_t err; - if (! err) - { - *types = 0; - if (fshelp_access (&node->nn_stat, S_IREAD, cred) == 0) - *types |= O_READ; - if (fshelp_access (&node->nn_stat, S_IWRITE, cred) == 0) - *types |= O_WRITE; - if (fshelp_access (&node->nn_stat, S_IEXEC, cred) == 0) - *types |= O_EXEC; - } + if (entry == 0) + procfs_refresh (dir); + + err = procfs_get_contents (dir, &contents, &contents_len); + if (err) + return err; - return err; -} + /* We depend on the fact that CONTENTS is terminated. */ + assert (contents_len == 0 || contents[contents_len - 1] == '\0'); -/* The granularity with which we allocate space to return our result. */ -#define DIRENTS_CHUNK_SIZE (8*1024) + /* Skip to the first requested entry. */ + while (contents_len && entry--) + { + int ofs = strlen (contents) + 1; + contents += ofs; + contents_len -= ofs; + } -/* Returned directory entries are aligned to blocks this many bytes long. - Must be a power of two. */ -#define DIRENT_ALIGN 4 -#define DIRENT_NAME_OFFS offsetof (struct dirent, d_name) + /* Allocate a buffer if necessary. */ + putentries (contents, contents_len, nentries, NULL, datacnt); + if (bufsize < *datacnt) + { + char *n = mmap (0, *datacnt, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, 0); + if (n == MAP_FAILED) + return ENOMEM; -/* Length is structure before the name + the name + '\0', all - padded to a four-byte alignment. */ -#define DIRENT_LEN(name_len) \ - ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) \ - & ~(DIRENT_ALIGN - 1)) + *data = n; + } + /* Do the actual conversion. */ + *amt = putentries (contents, contents_len, nentries, *data, datacnt); + return 0; +} -/* Fetch a directory */ -error_t -netfs_get_dirents (struct iouser *cred, struct node *dir, - int first_entry, int max_entries, char **data, - mach_msg_type_number_t *data_len, - vm_size_t max_data_len, int *data_entries) +/* The user must define this function. Lookup NAME in DIR (which is + locked) for USER; set *NP to the found name upon return. If the + name was not found, then return ENOENT. On any error, clear *NP. + (*NP, if found, should be locked and a reference to it generated. + This call should unlock DIR no matter what.) */ +error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, + char *name, struct node **np) { - error_t err = procfs_refresh_node (dir); - struct procfs_dir_entry *dir_entry; + error_t err; + + err = procfs_lookup (dir, name, np); + mutex_unlock (&dir->lock); if (! err) - { - if (dir->nn->dir) - { - if (! procfs_dir_refresh (dir->nn->dir, dir == dir->nn->fs->root)) - { - for (dir_entry = dir->nn->dir->ordered; first_entry > 0 && - dir_entry; first_entry--, - dir_entry = dir_entry->ordered_next); - if (! dir_entry ) - max_entries = 0; - - if (max_entries != 0) - { - size_t size = 0; - char *p; - int count = 0; - - - if (max_data_len == 0) - size = DIRENTS_CHUNK_SIZE; - else if (max_data_len > DIRENTS_CHUNK_SIZE) - size = DIRENTS_CHUNK_SIZE; - else - size = max_data_len; - - *data = mmap (0, size, PROT_READ|PROT_WRITE, - MAP_ANON, 0, 0); - - err = ((void *) *data == (void *) -1) ? errno : 0; - - if (! err) - { - p = *data; - - /* This gets all the actual entries present. */ - - while ((max_entries == -1 || count < max_entries) && dir_entry) - { - struct dirent hdr; - size_t name_len = strlen (dir_entry->name); - size_t sz = DIRENT_LEN (name_len); - int entry_type = IFTODT (dir_entry->stat.st_mode); - - if ((p - *data) + sz > size) - { - if (max_data_len > 0) - break; - else /* The Buffer Size must be increased. */ - { - vm_address_t extension = (vm_address_t)(*data + size); - err = vm_allocate (mach_task_self (), &extension, - DIRENTS_CHUNK_SIZE, 0); - - if (err) - break; - - size += DIRENTS_CHUNK_SIZE; - } - } - - hdr.d_namlen = name_len; - hdr.d_fileno = dir_entry->stat.st_ino; - hdr.d_reclen = sz; - hdr.d_type = entry_type; - - memcpy (p, &hdr, DIRENT_NAME_OFFS); - strcpy (p + DIRENT_NAME_OFFS, dir_entry->name); - - p += sz; - - count++; - dir_entry = dir_entry->ordered_next; - } - - if (err) - munmap (*data, size); - else - { - vm_address_t alloc_end = (vm_address_t)(*data + size); - vm_address_t real_end = round_page (p); - if (alloc_end > real_end) - munmap ((caddr_t) real_end, alloc_end - real_end); - *data_len = p - *data; - *data_entries = count; - } - } - } - else - { - *data_len = 0; - *data_entries = 0; - } - } - } - else - return ENOTDIR; - } - - procfs_dir_entries_remove (dir->nn->dir); + mutex_lock (&(*np)->lock); + return err; -} +} -/* Lookup NAME in DIR for USER; set *NODE to the found name upon return. If - the name was not found, then return ENOENT. On any error, clear *NODE. - (*NODE, if found, should be locked, this call should unlock DIR no matter - what.) */ -error_t netfs_attempt_lookup (struct iouser *user, struct node *dir, - char *name, struct node **node) +/* The user must define this function. Node NP has no more references; + free all its associated storage. */ +void netfs_node_norefs (struct node *np) { - error_t err = procfs_refresh_node (dir); + spin_unlock (&netfs_node_refcnt_lock); - if (! err) - err = procfs_dir_lookup (dir->nn->dir, name, node); + procfs_cleanup (np); + free (np); - return err; + spin_lock (&netfs_node_refcnt_lock); } -/* Delete NAME in DIR for USER. */ -error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, - char *name) + +/* Libnetfs callbacks managed with libfshelp. */ + +/* The user must define this function. Locked node NP is being opened + by USER, with FLAGS. NEWNODE is nonzero if we just created this + node. Return an error if we should not permit the open to complete + because of a permission restriction. */ +error_t netfs_check_open_permissions (struct iouser *user, struct node *np, + int flags, int newnode) { - return EROFS; + error_t err = 0; + if (!err && (flags & O_READ)) + err = fshelp_access (&np->nn_stat, S_IREAD, user); + if (!err && (flags & O_WRITE)) + err = fshelp_access (&np->nn_stat, S_IWRITE, user); + if (!err && (flags & O_EXEC)) + err = fshelp_access (&np->nn_stat, S_IEXEC, user); + return err; } -/* Note that in this one call, neither of the specific nodes are locked. */ -error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, - char *fromname, struct node *todir, - char *toname, int excl) +/* The user must define this function. Return the valid access + types (bitwise OR of O_READ, O_WRITE, and O_EXEC) in *TYPES for + locked file NP and user CRED. */ +error_t netfs_report_access (struct iouser *cred, struct node *np, + int *types) { - return EROFS; + *types = 0; + if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0) + *types |= O_READ; + if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0) + *types |= O_WRITE; + if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0) + *types |= O_EXEC; + return 0; } -/* This should attempt a chmod call for the user specified by CRED on node - NODE, to change the owner to UID and the group to GID. */ -error_t netfs_attempt_chown (struct iouser *cred, struct node *node, + +/* Trivial or unsupported libnetfs callbacks. */ + +/* The user must define this function. This should attempt a chmod + call for the user specified by CRED on locked node NP, to change + the owner to UID and the group to GID. */ +error_t netfs_attempt_chown (struct iouser *cred, struct node *np, uid_t uid, uid_t gid) { return EROFS; } -/* This should attempt a chauthor call for the user specified by CRED on node - NODE, to change the author to AUTHOR. */ -error_t netfs_attempt_chauthor (struct iouser *cred, struct node *node, +/* The user must define this function. This should attempt a chauthor + call for the user specified by CRED on locked node NP, thereby + changing the author to AUTHOR. */ +error_t netfs_attempt_chauthor (struct iouser *cred, struct node *np, uid_t author) { return EROFS; } -/* This should attempt a chmod call for the user specified by CRED on node - NODE, to change the mode to MODE. Unlike the normal Unix and Hurd meaning - of chmod, this function is also used to attempt to change files into other - types. If such a transition is attempted which is impossible, then return - EOPNOTSUPP. */ -error_t netfs_attempt_chmod (struct iouser *cred, struct node *node, +/* The user must define this function. This should attempt a chmod + call for the user specified by CRED on locked node NODE, to change + the mode to MODE. Unlike the normal Unix and Hurd meaning of + chmod, this function is also used to attempt to change files into + other types. If such a transition is attempted which is + impossible, then return EOPNOTSUPP. */ +error_t netfs_attempt_chmod (struct iouser *cred, struct node *np, mode_t mode) { return EROFS; } -/* Attempt to turn NODE (user CRED) into a symlink with target NAME. */ -error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *node, +/* The user must define this function. Attempt to turn locked node NP + (user CRED) into a symlink with target NAME. */ +error_t netfs_attempt_mksymlink (struct iouser *cred, struct node *np, char *name) { return EROFS; } -/* Attempt to turn NODE (user CRED) into a device. TYPE is either S_IFBLK or - S_IFCHR. */ -error_t netfs_attempt_mkdev (struct iouser *cred, struct node *node, +/* The user must define this function. Attempt to turn NODE (user + CRED) into a device. TYPE is either S_IFBLK or S_IFCHR. NP is + locked. */ +error_t netfs_attempt_mkdev (struct iouser *cred, struct node *np, mode_t type, dev_t indexes) { return EROFS; } - -/* This should attempt a chflags call for the user specified by CRED on node - NODE, to change the flags to FLAGS. */ -error_t netfs_attempt_chflags (struct iouser *cred, struct node *node, +/* The user must define this function. This should attempt a chflags + call for the user specified by CRED on locked node NP, to change + the flags to FLAGS. */ +error_t netfs_attempt_chflags (struct iouser *cred, struct node *np, int flags) { return EROFS; } -/* This should attempt to set the size of the file NODE (for user CRED) to - SIZE bytes long. */ -error_t netfs_attempt_set_size (struct iouser *cred, struct node *node, - off_t size) +/* The user must define this function. This should attempt a utimes + call for the user specified by CRED on locked node NP, to change + the atime to ATIME and the mtime to MTIME. If ATIME or MTIME is + null, then set to the current time. */ +error_t netfs_attempt_utimes (struct iouser *cred, struct node *np, + struct timespec *atime, struct timespec *mtime) +{ + return EROFS; +} + +/* The user must define this function. This should attempt to set the + size of the locked file NP (for user CRED) to SIZE bytes long. */ +error_t netfs_attempt_set_size (struct iouser *cred, struct node *np, + loff_t size) { return EROFS; } -/* This should attempt to fetch filesystem status information for the remote - filesystem, for the user CRED. */ -error_t -netfs_attempt_statfs (struct iouser *cred, struct node *node, - struct statfs *st) +/* The user must define this function. This should attempt to fetch + filesystem status information for the remote filesystem, for the + user CRED. NP is locked. */ +error_t netfs_attempt_statfs (struct iouser *cred, struct node *np, + fsys_statfsbuf_t *st) +{ + return ENOSYS; +} + +/* The user must define this function. This should sync the locked + file NP completely to disk, for the user CRED. If WAIT is set, + return only after the sync is completely finished. */ +error_t netfs_attempt_sync (struct iouser *cred, struct node *np, + int wait) { - bzero (st, sizeof *st); - st->f_type = PROCFILESYSTEM; - st->f_fsid = getpid (); return 0; } -/* This should sync the entire remote filesystem. If WAIT is set, return - only after sync is completely finished. */ +/* The user must define this function. This should sync the entire + remote filesystem. If WAIT is set, return only after the sync is + completely finished. */ error_t netfs_attempt_syncfs (struct iouser *cred, int wait) { return 0; } -/* Create a link in DIR with name NAME to FILE for USER. Note that neither - DIR nor FILE are locked. If EXCL is set, do not delete the target, but - return EEXIST if NAME is already found in DIR. */ -error_t netfs_attempt_link (struct iouser *user, struct node *dir, - struct node *file, char *name, int excl) +/* The user must define this function. Delete NAME in DIR (which is + locked) for USER. */ +error_t netfs_attempt_unlink (struct iouser *user, struct node *dir, + char *name) { return EROFS; } -/* Attempt to create an anonymous file related to DIR for USER with MODE. - Set *NODE to the returned file upon success. No matter what, unlock DIR. */ -error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, - mode_t mode, struct node **node) +/* The user must define this function. Attempt to rename the + directory FROMDIR to TODIR. Note that neither of the specific nodes + are locked. */ +error_t netfs_attempt_rename (struct iouser *user, struct node *fromdir, + char *fromname, struct node *todir, + char *toname, int excl) { - *node = NULL; - mutex_unlock (&dir->lock); return EROFS; } -/* Read the contents of NODE (a symlink), for USER, into BUF. */ -error_t netfs_attempt_readlink (struct iouser *user, struct node *node, char *buf) +/* The user must define this function. Attempt to create a new + directory named NAME in DIR (which is locked) for USER with mode + MODE. */ +error_t netfs_attempt_mkdir (struct iouser *user, struct node *dir, + char *name, mode_t mode) { - error_t err = procfs_refresh_node (node); - if (! err) - { - struct procfs_dir_entry *dir_entry = node->nn->dir_entry; - if (dir_entry) - bcopy (dir_entry->symlink_target, buf, node->nn_stat.st_size); - else - err = EINVAL; - } - return err; + return EROFS; } -/* Read from the file NODE for user CRED starting at OFFSET and continuing for - up to *LEN bytes. Put the data at DATA. Set *LEN to the amount - successfully read upon return. */ -error_t netfs_attempt_read (struct iouser *cred, struct node *node, - off_t offset, size_t *len, void *data) +/* The user must define this function. Attempt to remove directory + named NAME in DIR (which is locked) for USER. */ +error_t netfs_attempt_rmdir (struct iouser *user, + struct node *dir, char *name) { - error_t err; - err = procfs_refresh_node (node); + return EROFS; +} - if (! err) - { - if (*len > 0) - procfs_read_files_contents (node, offset, - len, data); - if (*len > 0) - if (offset >= *len) - *len = 0; - } - return err; +/* The user must define this function. Create a link in DIR with name + NAME to FILE for USER. Note that neither DIR nor FILE are + locked. If EXCL is set, do not delete the target. Return EEXIST if + NAME is already found in DIR. */ +error_t netfs_attempt_link (struct iouser *user, struct node *dir, + struct node *file, char *name, int excl) +{ + return EROFS; +} + +/* The user must define this function. Attempt to create an anonymous + file related to DIR (which is locked) for USER with MODE. Set *NP + to the returned file upon success. No matter what, unlock DIR. */ +error_t netfs_attempt_mkfile (struct iouser *user, struct node *dir, + mode_t mode, struct node **np) +{ + return EROFS; } -/* Write to the file NODE for user CRED starting at OFFSET and continuing for up - to *LEN bytes from DATA. Set *LEN to the amount seccessfully written upon - return. */ -error_t netfs_attempt_write (struct iouser *cred, struct node *node, - off_t offset, size_t *len, void *data) +/* The user must define this function. Attempt to create a file named + NAME in DIR (which is locked) for USER with MODE. Set *NP to the + new node upon return. On any error, clear *NP. *NP should be + locked on success; no matter what, unlock DIR before returning. */ +error_t netfs_attempt_create_file (struct iouser *user, struct node *dir, + char *name, mode_t mode, struct node **np) { return EROFS; } -/* The user must define this function. Node NP is all done; free - all its associated storage. */ -void netfs_node_norefs (struct node *np) +/* The user must define this function. Write to the locked file NP + for user CRED starting at OFSET and continuing for up to *LEN bytes + from DATA. Set *LEN to the amount successfully written upon + return. */ +error_t netfs_attempt_write (struct iouser *cred, struct node *np, + loff_t offset, size_t *len, void *data) { - mutex_lock (&np->lock); - *np->prevp = np->next; - np->next->prevp = np->prevp; - procfs_remove_node (np); + return EROFS; } + |