blob: 87dcece7e1b5cc1d0439da96c7fffe5199af1311 [file] [log] [blame]
Herbert Poetzlca4d1472006-07-03 17:27:12 -07001/*
2 * linux/fs/ocfs2/ioctl.c
3 *
4 * Copyright (C) 2006 Herbert Poetzl
5 * adapted from Remy Card's ext2/ioctl.c
6 */
7
8#include <linux/fs.h>
9#include <linux/mount.h>
10
11#define MLOG_MASK_PREFIX ML_INODE
12#include <cluster/masklog.h>
13
14#include "ocfs2.h"
15#include "alloc.h"
16#include "dlmglue.h"
Mark Fashehb2580102007-03-09 16:53:21 -080017#include "file.h"
Herbert Poetzlca4d1472006-07-03 17:27:12 -070018#include "inode.h"
19#include "journal.h"
20
21#include "ocfs2_fs.h"
Adrian Bunk2d562512006-07-10 01:32:51 +020022#include "ioctl.h"
23
Herbert Poetzlca4d1472006-07-03 17:27:12 -070024#include <linux/ext2_fs.h>
25
26static int ocfs2_get_inode_attr(struct inode *inode, unsigned *flags)
27{
28 int status;
29
Mark Fasheh4bcec182006-10-09 16:02:40 -070030 status = ocfs2_meta_lock(inode, NULL, 0);
Herbert Poetzlca4d1472006-07-03 17:27:12 -070031 if (status < 0) {
32 mlog_errno(status);
33 return status;
34 }
Jan Kara6e4b0d52007-04-27 11:08:01 -070035 ocfs2_get_inode_flags(OCFS2_I(inode));
Herbert Poetzlca4d1472006-07-03 17:27:12 -070036 *flags = OCFS2_I(inode)->ip_attr;
37 ocfs2_meta_unlock(inode, 0);
38
39 mlog_exit(status);
40 return status;
41}
42
43static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
44 unsigned mask)
45{
46 struct ocfs2_inode_info *ocfs2_inode = OCFS2_I(inode);
47 struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
Mark Fasheh1fabe142006-10-09 18:11:45 -070048 handle_t *handle = NULL;
Herbert Poetzlca4d1472006-07-03 17:27:12 -070049 struct buffer_head *bh = NULL;
50 unsigned oldflags;
51 int status;
52
53 mutex_lock(&inode->i_mutex);
54
Mark Fasheh4bcec182006-10-09 16:02:40 -070055 status = ocfs2_meta_lock(inode, &bh, 1);
Herbert Poetzlca4d1472006-07-03 17:27:12 -070056 if (status < 0) {
57 mlog_errno(status);
58 goto bail;
59 }
60
61 status = -EROFS;
62 if (IS_RDONLY(inode))
63 goto bail_unlock;
64
65 status = -EACCES;
Satyam Sharma3bd858a2007-07-17 15:00:08 +053066 if (!is_owner_or_cap(inode))
Herbert Poetzlca4d1472006-07-03 17:27:12 -070067 goto bail_unlock;
68
69 if (!S_ISDIR(inode->i_mode))
70 flags &= ~OCFS2_DIRSYNC_FL;
71
Mark Fasheh65eff9c2006-10-09 17:26:22 -070072 handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS);
Herbert Poetzlca4d1472006-07-03 17:27:12 -070073 if (IS_ERR(handle)) {
74 status = PTR_ERR(handle);
75 mlog_errno(status);
76 goto bail_unlock;
77 }
78
79 oldflags = ocfs2_inode->ip_attr;
80 flags = flags & mask;
81 flags |= oldflags & ~mask;
82
83 /*
84 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
85 * the relevant capability.
86 */
87 status = -EPERM;
88 if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
89 (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
90 if (!capable(CAP_LINUX_IMMUTABLE))
91 goto bail_unlock;
92 }
93
94 ocfs2_inode->ip_attr = flags;
95 ocfs2_set_inode_flags(inode);
96
97 status = ocfs2_mark_inode_dirty(handle, inode, bh);
98 if (status < 0)
99 mlog_errno(status);
100
Mark Fasheh02dc1af2006-10-09 16:48:10 -0700101 ocfs2_commit_trans(osb, handle);
Herbert Poetzlca4d1472006-07-03 17:27:12 -0700102bail_unlock:
103 ocfs2_meta_unlock(inode, 1);
104bail:
105 mutex_unlock(&inode->i_mutex);
106
107 if (bh)
108 brelse(bh);
109
110 mlog_exit(status);
111 return status;
112}
113
114int ocfs2_ioctl(struct inode * inode, struct file * filp,
115 unsigned int cmd, unsigned long arg)
116{
117 unsigned int flags;
118 int status;
Mark Fashehb2580102007-03-09 16:53:21 -0800119 struct ocfs2_space_resv sr;
Herbert Poetzlca4d1472006-07-03 17:27:12 -0700120
121 switch (cmd) {
122 case OCFS2_IOC_GETFLAGS:
123 status = ocfs2_get_inode_attr(inode, &flags);
124 if (status < 0)
125 return status;
126
127 flags &= OCFS2_FL_VISIBLE;
128 return put_user(flags, (int __user *) arg);
129 case OCFS2_IOC_SETFLAGS:
130 if (get_user(flags, (int __user *) arg))
131 return -EFAULT;
132
133 return ocfs2_set_inode_attr(inode, flags,
134 OCFS2_FL_MODIFIABLE);
Mark Fashehb2580102007-03-09 16:53:21 -0800135 case OCFS2_IOC_RESVSP:
136 case OCFS2_IOC_RESVSP64:
137 case OCFS2_IOC_UNRESVSP:
138 case OCFS2_IOC_UNRESVSP64:
139 if (copy_from_user(&sr, (int __user *) arg, sizeof(sr)))
140 return -EFAULT;
141
142 return ocfs2_change_file_space(filp, cmd, &sr);
Herbert Poetzlca4d1472006-07-03 17:27:12 -0700143 default:
144 return -ENOTTY;
145 }
146}
147
Mark Fasheh586d2322007-03-09 15:56:28 -0800148#ifdef CONFIG_COMPAT
149long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
150{
151 struct inode *inode = file->f_path.dentry->d_inode;
152 int ret;
153
154 switch (cmd) {
155 case OCFS2_IOC32_GETFLAGS:
156 cmd = OCFS2_IOC_GETFLAGS;
157 break;
158 case OCFS2_IOC32_SETFLAGS:
159 cmd = OCFS2_IOC_SETFLAGS;
160 break;
Mark Fashehb2580102007-03-09 16:53:21 -0800161 case OCFS2_IOC_RESVSP:
162 case OCFS2_IOC_RESVSP64:
163 case OCFS2_IOC_UNRESVSP:
164 case OCFS2_IOC_UNRESVSP64:
165 break;
Mark Fasheh586d2322007-03-09 15:56:28 -0800166 default:
167 return -ENOIOCTLCMD;
168 }
169
170 lock_kernel();
171 ret = ocfs2_ioctl(inode, file, cmd, arg);
172 unlock_kernel();
173 return ret;
174}
175#endif